From a8d01a5e18fc6f8fc68dfd24daff5600ab69a024 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Tue, 24 Feb 2026 11:30:47 +0800 Subject: [PATCH 001/130] [SPARK-54868][PYTHON][INFRA][FOLLOWUP] Add PYSPARK_TEST_TIMEOUT to hosted runner test action ### What changes were proposed in this pull request? Add `PYSPARK_TEST_TIMEOUT` to hosted runner test action. ### Why are the changes needed? The test could stuck in hosted runners: https://github.com/apache/spark/actions/runs/22286360532 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? action change. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54431 from gaogaotiantian/add-timeout-hosted-runner. Authored-by: Tian Gao Signed-off-by: Ruifeng Zheng --- .github/workflows/python_hosted_runner_test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/python_hosted_runner_test.yml b/.github/workflows/python_hosted_runner_test.yml index eac38ee1e9111..235d8e0064ca2 100644 --- a/.github/workflows/python_hosted_runner_test.yml +++ b/.github/workflows/python_hosted_runner_test.yml @@ -102,6 +102,7 @@ jobs: SKIP_PACKAGING: true METASPACE_SIZE: 1g BRANCH: ${{ inputs.branch }} + PYSPARK_TEST_TIMEOUT: 450 steps: - name: Checkout Spark repository uses: actions/checkout@v6 From 730e239224386999683b0537573262ccedef6821 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Mon, 23 Feb 2026 19:59:38 -0800 Subject: [PATCH 002/130] [SPARK-55643][INFRA] Add connection timeout to JIRA client to prevent hanging and enable retries ### What changes were proposed in this pull request? This PR aims to add a generic connection and read timeout parameter timeout=(3.05, 30) to the `jira.client.JIRA()` initializations in the `dev/merge_spark_pr.py` script. ### Why are the changes needed? By default, the `requests` library (used by the jira python package) can hang indefinitely when attempting to establish a connection if the server is unresponsive. Setting a short connection timeout of 3.05 seconds (slightly larger than a standard 3-second TCP packet retransmission window) ensures that the client will quickly fail the connection attempt and properly trigger its internal retry logic, rather than stalling the entire script. The 30-second read timeout allows sufficient time for normal API responses once the connection is successfully established. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Manual tests. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54432 from dongjoon-hyun/SPARK-55643. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- dev/merge_spark_pr.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dev/merge_spark_pr.py b/dev/merge_spark_pr.py index ff38253bcf536..1eef16aa229f6 100755 --- a/dev/merge_spark_pr.py +++ b/dev/merge_spark_pr.py @@ -573,7 +573,7 @@ def initialize_jira(): print_error("ERROR finding jira library. Run 'pip3 install jira' to install.") continue_maybe("Continue without jira?") elif JIRA_ACCESS_TOKEN: - client = jira.client.JIRA(jira_server, token_auth=JIRA_ACCESS_TOKEN) + client = jira.client.JIRA(jira_server, token_auth=JIRA_ACCESS_TOKEN, timeout=(3.05, 30)) try: # Eagerly check if the token is valid to align with the behavior of username/password # authn @@ -592,7 +592,9 @@ def initialize_jira(): print("You can use JIRA_ACCESS_TOKEN instead of JIRA_USERNAME/JIRA_PASSWORD.") print("Visit https://issues.apache.org/jira/secure/ViewProfile.jspa ") print("and click 'Personal Access Tokens' menu to manage your own tokens.") - asf_jira = jira.client.JIRA(jira_server, basic_auth=(JIRA_USERNAME, JIRA_PASSWORD)) + asf_jira = jira.client.JIRA( + jira_server, basic_auth=(JIRA_USERNAME, JIRA_PASSWORD), timeout=(3.05, 30) + ) else: print("Neither JIRA_ACCESS_TOKEN nor JIRA_USERNAME/JIRA_PASSWORD are set.") continue_maybe("Continue without jira?") From 37e4c2d1883d8ce356cd5dbae555571443c8115a Mon Sep 17 00:00:00 2001 From: huanliwang-db Date: Tue, 24 Feb 2026 12:32:37 +0800 Subject: [PATCH 003/130] [SPARK-55646][SQL] Refactored SQLExecution.withThreadLocalCaptured to separate thread-local capture from execution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? Previously, callers had to provide an ExecutorService upfront: thread-local capture and task submission were fused into a single call that immediately returned a CompletableFuture. Now, captureThreadLocals(sparkSession) captures the current thread's SQL context into a standalone SQLExecutionThreadLocalCaptured object. Callers can then invoke `runWith { body }` on any thread, at any time, using any concurrency primitive — not just ExecutorService. `withThreadLocalCaptured` is preserved for backward compatibility and now delegates to these two primitives. ### Why are the changes needed? Refactoring to make withThreadLocalCaptured easier to use. ### Does this PR introduce _any_ user-facing change? NO ### How was this patch tested? Existing UTs ### Was this patch authored or co-authored using generative AI tooling? No Closes #54434 from huanliwang-db/huanliwang-db/refactor-sqlthread. Authored-by: huanliwang-db Signed-off-by: Wenchen Fan --- .../spark/sql/execution/SQLExecution.scala | 76 +++++++++++++------ 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/SQLExecution.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/SQLExecution.scala index 96a0053f97b1d..f25e908a9cdb7 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/SQLExecution.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/SQLExecution.scala @@ -23,7 +23,7 @@ import java.util.concurrent.atomic.AtomicLong import scala.jdk.CollectionConverters._ import scala.util.control.NonFatal -import org.apache.spark.{ErrorMessageFormat, JobArtifactSet, SparkContext, SparkEnv, SparkException, SparkThrowable, SparkThrowableHelper} +import org.apache.spark.{ErrorMessageFormat, JobArtifactSet, JobArtifactState, SparkContext, SparkEnv, SparkException, SparkThrowable, SparkThrowableHelper} import org.apache.spark.SparkContext.{SPARK_JOB_DESCRIPTION, SPARK_JOB_INTERRUPT_ON_CANCEL} import org.apache.spark.internal.Logging import org.apache.spark.internal.config.{SPARK_DRIVER_PREFIX, SPARK_EXECUTOR_PREFIX} @@ -38,6 +38,43 @@ import org.apache.spark.sql.internal.SQLConf import org.apache.spark.sql.internal.StaticSQLConf.SQL_EVENT_TRUNCATE_LENGTH import org.apache.spark.util.{Utils, UUIDv7Generator} +/** + * Captures SQL-specific thread-local variables so they can be restored on a different thread. + * Use [[SQLExecution.captureThreadLocals]] to create an instance on the originating thread, + * then call [[runWith]] on the target thread to execute a block with these thread locals applied. + */ +case class SQLExecutionThreadLocalCaptured( + sparkSession: SparkSession, + localProps: java.util.Properties, + artifactState: JobArtifactState) { + + /** + * Run the given body with the captured thread-local variables applied on the current thread. + * Original thread-local values are saved and restored after the body completes. + */ + def runWith[T](body: => T): T = { + val sc = sparkSession.sparkContext + JobArtifactSet.withActiveJobArtifactState(artifactState) { + val originalSession = SparkSession.getActiveSession + val originalLocalProps = sc.getLocalProperties + SparkSession.setActiveSession(sparkSession) + val res = SQLExecution.withSessionTagsApplied(sparkSession) { + sc.setLocalProperties(localProps) + val res = body + // reset active session and local props. + sc.setLocalProperties(originalLocalProps) + res + } + if (originalSession.nonEmpty) { + SparkSession.setActiveSession(originalSession.get) + } else { + SparkSession.clearActiveSession() + } + res + } + } +} + object SQLExecution extends Logging { val EXECUTION_ID_KEY = "spark.sql.execution.id" @@ -343,36 +380,25 @@ object SQLExecution extends Logging { } } + def captureThreadLocals(sparkSession: SparkSession): SQLExecutionThreadLocalCaptured = { + val sc = sparkSession.sparkContext + val localProps = Utils.cloneProperties(sc.getLocalProperties) + // `getCurrentJobArtifactState` will return a stat only in Spark Connect mode. In non-Connect + // mode, we default back to the resources of the current Spark session. + val artifactState = + JobArtifactSet.getCurrentJobArtifactState.getOrElse(sparkSession.artifactManager.state) + SQLExecutionThreadLocalCaptured(sparkSession, localProps, artifactState) + } + /** * Wrap passed function to ensure necessary thread-local variables like * SparkContext local properties are forwarded to execution thread */ def withThreadLocalCaptured[T]( sparkSession: SparkSession, exec: ExecutorService) (body: => T): CompletableFuture[T] = { - val activeSession = sparkSession - val sc = sparkSession.sparkContext - val localProps = Utils.cloneProperties(sc.getLocalProperties) - // `getCurrentJobArtifactState` will return a stat only in Spark Connect mode. In non-Connect - // mode, we default back to the resources of the current Spark session. - val artifactState = JobArtifactSet.getCurrentJobArtifactState.getOrElse( - activeSession.artifactManager.state) - CompletableFuture.supplyAsync(() => JobArtifactSet.withActiveJobArtifactState(artifactState) { - val originalSession = SparkSession.getActiveSession - val originalLocalProps = sc.getLocalProperties - SparkSession.setActiveSession(activeSession) - val res = withSessionTagsApplied(activeSession) { - sc.setLocalProperties(localProps) - val res = body - // reset active session and local props. - sc.setLocalProperties(originalLocalProps) - res - } - if (originalSession.nonEmpty) { - SparkSession.setActiveSession(originalSession.get) - } else { - SparkSession.clearActiveSession() - } - res + val threadLocalCaptured = captureThreadLocals(sparkSession) + CompletableFuture.supplyAsync(() => { + threadLocalCaptured.runWith(body) }, exec) } } From 2f3772493c490621823e10ef2db1f4f6a81fbc4c Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Mon, 23 Feb 2026 20:59:14 -0800 Subject: [PATCH 004/130] [SPARK-55649][K8S] Promote `Kubernetes(Driver|Executor)?FeatureConfigStep` traits to `Stable` ### What changes were proposed in this pull request? This PR aims to promote the following traits to `Stable` from Apache Spark 4.2.0: - `KubernetesFeatureConfigStep` - `KubernetesDriverCustomFeatureConfigStep` - `KubernetesExecutorCustomFeatureConfigStep` ### Why are the changes needed? Since Apache Spark 3.3.0, the `Kubernetes*FeatureConfigStep` traits have been serving stably without any modifications for 4 years. We had better promote them to `Stable`. - https://github.com/apache/spark/pull/35345 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Pass the CIs. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54439 from dongjoon-hyun/SPARK-55649. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- docs/running-on-kubernetes.md | 4 ++-- .../features/KubernetesDriverCustomFeatureConfigStep.scala | 5 +++-- .../features/KubernetesExecutorCustomFeatureConfigStep.scala | 5 +++-- .../deploy/k8s/features/KubernetesFeatureConfigStep.scala | 5 +++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/running-on-kubernetes.md b/docs/running-on-kubernetes.md index 46efb479a2fe3..c1d50f3ecfb3e 100644 --- a/docs/running-on-kubernetes.md +++ b/docs/running-on-kubernetes.md @@ -1611,7 +1611,7 @@ See the [configuration page](configuration.html) for information on Spark config (none) Class names of an extra driver pod feature step implementing - `KubernetesFeatureConfigStep`. This is a developer API. Comma separated. + `KubernetesFeatureConfigStep`. This is a stable developer API. Comma separated. Runs after all of Spark internal feature steps. Since 3.3.0, your driver feature step can implement `KubernetesDriverCustomFeatureConfigStep` where the driver config is also available. @@ -1632,7 +1632,7 @@ See the [configuration page](configuration.html) for information on Spark config (none) Class names of an extra executor pod feature step implementing - `KubernetesFeatureConfigStep`. This is a developer API. Comma separated. + `KubernetesFeatureConfigStep`. This is a stable developer API. Comma separated. Runs after all of Spark internal feature steps. Since 3.3.0, your executor feature step can implement `KubernetesExecutorCustomFeatureConfigStep` where the executor config is also available. diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesDriverCustomFeatureConfigStep.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesDriverCustomFeatureConfigStep.scala index 0edd94d3370ab..84392f897ae30 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesDriverCustomFeatureConfigStep.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesDriverCustomFeatureConfigStep.scala @@ -16,7 +16,7 @@ */ package org.apache.spark.deploy.k8s.features -import org.apache.spark.annotation.{DeveloperApi, Unstable} +import org.apache.spark.annotation.{DeveloperApi, Since, Stable} import org.apache.spark.deploy.k8s.KubernetesDriverConf /** @@ -65,8 +65,9 @@ import org.apache.spark.deploy.k8s.KubernetesDriverConf * } * }}} */ -@Unstable +@Stable @DeveloperApi +@Since("3.3.0") trait KubernetesDriverCustomFeatureConfigStep extends KubernetesFeatureConfigStep { /** * Initialize the configuration for driver user feature step, this only applicable when user diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesExecutorCustomFeatureConfigStep.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesExecutorCustomFeatureConfigStep.scala index dfb1c768c990e..6a1505ce78133 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesExecutorCustomFeatureConfigStep.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesExecutorCustomFeatureConfigStep.scala @@ -16,7 +16,7 @@ */ package org.apache.spark.deploy.k8s.features -import org.apache.spark.annotation.{DeveloperApi, Unstable} +import org.apache.spark.annotation.{DeveloperApi, Since, Stable} import org.apache.spark.deploy.k8s.KubernetesExecutorConf /** @@ -65,8 +65,9 @@ import org.apache.spark.deploy.k8s.KubernetesExecutorConf * } * }}} */ -@Unstable +@Stable @DeveloperApi +@Since("3.3.0") trait KubernetesExecutorCustomFeatureConfigStep extends KubernetesFeatureConfigStep { /** * Initialize the configuration for executor user feature step, this only applicable when user diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesFeatureConfigStep.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesFeatureConfigStep.scala index fcb789f4ae7f4..1f5776dd26dc8 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesFeatureConfigStep.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/KubernetesFeatureConfigStep.scala @@ -18,7 +18,7 @@ package org.apache.spark.deploy.k8s.features import io.fabric8.kubernetes.api.model.HasMetadata -import org.apache.spark.annotation.{DeveloperApi, Unstable} +import org.apache.spark.annotation.{DeveloperApi, Since, Stable} import org.apache.spark.deploy.k8s.SparkPod /** @@ -27,8 +27,9 @@ import org.apache.spark.deploy.k8s.SparkPod * A collection of functions that together represent a "feature" in pods that are launched for * Spark drivers and executors. */ -@Unstable +@Stable @DeveloperApi +@Since("3.3.0") trait KubernetesFeatureConfigStep { /** From 178bcecb9c2f3b980bf6ab27bb2fbb16b1b87fdc Mon Sep 17 00:00:00 2001 From: Parth Chandra Date: Mon, 23 Feb 2026 21:07:55 -0800 Subject: [PATCH 005/130] [SPARK-55075][K8S] Track executor pod creation errors with ExecutorFailureTracker ### What changes were proposed in this pull request? Adds tracking of executor pod creation with the ExecutorFailureTracker. ### Why are the changes needed? If there are unrecoverable pod creation errors then Spark continues to try and create pods instead of failing. An example is where a note book server is constrained to have a maximum number of pods and the user tries to start a notebook with twice the number of executors as the limit. In this case the user gets and 'Unauthorized' message in the logs but Spark will keep on trying to spin up new pods. By tracking pod creation failures we can stop trying after reaching max executor failures. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? New unit tests added ### Was this patch authored or co-authored using generative AI tooling? Unit tests generated using Claude Code. Closes #53840 from parthchandra/k8s-failures. Authored-by: Parth Chandra Signed-off-by: Dongjoon Hyun --- .../cluster/k8s/AbstractPodsAllocator.scala | 14 ++++ .../cluster/k8s/ExecutorPodsAllocator.scala | 84 +++++++++++++------ .../k8s/ExecutorPodsLifecycleManager.scala | 8 ++ .../k8s/KubernetesClusterManager.scala | 21 +++-- .../k8s/ExecutorPodsAllocatorSuite.scala | 28 +++++++ 5 files changed, 126 insertions(+), 29 deletions(-) diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/AbstractPodsAllocator.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/AbstractPodsAllocator.scala index cc081202cf89a..8803d3d031e47 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/AbstractPodsAllocator.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/AbstractPodsAllocator.scala @@ -35,6 +35,20 @@ import org.apache.spark.resource.ResourceProfile */ @DeveloperApi abstract class AbstractPodsAllocator { + /* + * Optional lifecycle manager for tracking executor pod lifecycle events. + * Set via setExecutorPodsLifecycleManager for backward compatibility. + */ + protected var executorPodsLifecycleManager: Option[ExecutorPodsLifecycleManager] = None + + /* + * Set the lifecycle manager for tracking executor pod lifecycle events. + * This method is optional and may not exist in custom implementations based on older versions. + */ + def setExecutorPodsLifecycleManager(manager: ExecutorPodsLifecycleManager): Unit = { + executorPodsLifecycleManager = Some(manager) + } + /* * Set the total expected executors for an application */ diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocator.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocator.scala index 126d07c0926f4..340cc9c76e46f 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocator.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocator.scala @@ -118,6 +118,9 @@ class ExecutorPodsAllocator( protected val numOutstandingPods = new AtomicInteger() + // Track total failed pod creation attempts across the application lifecycle + protected val totalFailedPodCreations = new AtomicInteger(0) + protected var lastSnapshot = ExecutorPodsSnapshot() protected var appId: String = _ @@ -459,32 +462,55 @@ class ExecutorPodsAllocator( .build() val resources = replacePVCsIfNeeded( podWithAttachedContainer, resolvedExecutorSpec.executorKubernetesResources, reusablePVCs) - val createdExecutorPod = - kubernetesClient.pods().inNamespace(namespace).resource(podWithAttachedContainer).create() - try { - addOwnerReference(createdExecutorPod, resources) - resources - .filter(_.getKind == "PersistentVolumeClaim") - .foreach { resource => - if (conf.get(KUBERNETES_DRIVER_OWN_PVC) && driverPod.nonEmpty) { - addOwnerReference(driverPod.get, Seq(resource)) - } - val pvc = resource.asInstanceOf[PersistentVolumeClaim] - logInfo(log"Trying to create PersistentVolumeClaim " + - log"${MDC(LogKeys.PVC_METADATA_NAME, pvc.getMetadata.getName)} with " + - log"StorageClass ${MDC(LogKeys.CLASS_NAME, pvc.getSpec.getStorageClassName)}") - kubernetesClient.persistentVolumeClaims().inNamespace(namespace).resource(pvc).create() - PVC_COUNTER.incrementAndGet() - } - newlyCreatedExecutors(newExecutorId) = (resourceProfileId, clock.getTimeMillis()) - logDebug(s"Requested executor with id $newExecutorId from Kubernetes.") + val optCreatedExecutorPod = try { + Some(kubernetesClient + .pods() + .inNamespace(namespace) + .resource(podWithAttachedContainer) + .create()) } catch { case NonFatal(e) => - kubernetesClient.pods() - .inNamespace(namespace) - .resource(createdExecutorPod) - .delete() - throw e + // Register failure with global tracker if lifecycle manager is available + val failureCount = registerPodCreationFailure() + logError(log"Failed to create executor pod ${MDC(LogKeys.EXECUTOR_ID, newExecutorId)}. " + + log"Total failures: ${MDC(LogKeys.TOTAL, failureCount)}", e) + None + } + optCreatedExecutorPod.foreach { createdExecutorPod => + try { + addOwnerReference(createdExecutorPod, resources) + resources + .filter(_.getKind == "PersistentVolumeClaim") + .foreach { resource => + if (conf.get(KUBERNETES_DRIVER_OWN_PVC) && driverPod.nonEmpty) { + addOwnerReference(driverPod.get, Seq(resource)) + } + val pvc = resource.asInstanceOf[PersistentVolumeClaim] + logInfo(log"Trying to create PersistentVolumeClaim " + + log"${MDC(LogKeys.PVC_METADATA_NAME, pvc.getMetadata.getName)} with " + + log"StorageClass ${MDC(LogKeys.CLASS_NAME, pvc.getSpec.getStorageClassName)}") + kubernetesClient + .persistentVolumeClaims() + .inNamespace(namespace) + .resource(pvc) + .create() + PVC_COUNTER.incrementAndGet() + } + newlyCreatedExecutors(newExecutorId) = (resourceProfileId, clock.getTimeMillis()) + logDebug(s"Requested executor with id $newExecutorId from Kubernetes.") + } catch { + case NonFatal(e) => + // Register failure with global tracker if lifecycle manager is available + val failureCount = registerPodCreationFailure() + logError(log"Failed to add owner reference or create PVC for executor pod " + + log"${MDC(LogKeys.EXECUTOR_ID, newExecutorId)}. " + + log"Total failures: ${MDC(LogKeys.TOTAL, failureCount)}", e) + kubernetesClient.pods() + .inNamespace(namespace) + .resource(createdExecutorPod) + .delete() + throw e + } } } } @@ -521,6 +547,16 @@ class ExecutorPodsAllocator( resources.filterNot(replacedResources.contains) } + /** + * Registers a pod creation failure with the lifecycle manager and increments the local counter. + * Returns the total failure count for logging purposes. + */ + protected def registerPodCreationFailure(): Int = { + val failureCount = totalFailedPodCreations.incrementAndGet() + executorPodsLifecycleManager.foreach(_.registerExecutorFailure()) + failureCount + } + protected def isExecutorIdleTimedOut(state: ExecutorPodState, currentTime: Long): Boolean = { try { val creationTime = Instant.parse(state.pod.getMetadata.getCreationTimestamp).toEpochMilli() diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsLifecycleManager.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsLifecycleManager.scala index c57a014dcfa67..84cfd0d72b3bb 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsLifecycleManager.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsLifecycleManager.scala @@ -77,6 +77,14 @@ private[spark] class ExecutorPodsLifecycleManager( protected[spark] def getNumExecutorsFailed: Int = failureTracker.numFailedExecutors + /** + * Register an executor failure. This increments the global executor failure count + * which is checked against spark.executor.maxNumFailures. + */ + protected[spark] def registerExecutorFailure(): Unit = { + failureTracker.registerExecutorFailure() + } + def start(schedulerBackend: KubernetesClusterSchedulerBackend): Unit = { val eventProcessingInterval = conf.get(KUBERNETES_EXECUTOR_EVENT_PROCESSING_INTERVAL) snapshotsStore.addSubscriber(eventProcessingInterval) { executorPodsSnapshot => diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterManager.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterManager.scala index d2c6789f2bb5a..782fac670fa88 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterManager.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterManager.scala @@ -134,7 +134,8 @@ private[spark] class KubernetesClusterManager extends ExternalClusterManager wit kubernetesClient, snapshotsStore) - val executorPodsAllocator = makeExecutorPodsAllocator(sc, kubernetesClient, snapshotsStore) + val executorPodsAllocator = makeExecutorPodsAllocator( + sc, kubernetesClient, snapshotsStore, Some(executorPodsLifecycleManager)) val podsWatchEventSource = new ExecutorPodsWatchSnapshotSource( snapshotsStore, @@ -158,8 +159,11 @@ private[spark] class KubernetesClusterManager extends ExternalClusterManager wit podsPollingEventSource) } - private[k8s] def makeExecutorPodsAllocator(sc: SparkContext, kubernetesClient: KubernetesClient, - snapshotsStore: ExecutorPodsSnapshotsStore) = { + private[k8s] def makeExecutorPodsAllocator( + sc: SparkContext, + kubernetesClient: KubernetesClient, + snapshotsStore: ExecutorPodsSnapshotsStore, + lifecycleManager: Option[ExecutorPodsLifecycleManager] = None) = { val allocator = sc.conf.get(KUBERNETES_ALLOCATION_PODS_ALLOCATOR) if (allocator == "deployment" && Utils.isDynamicAllocationEnabled(sc.conf) && sc.conf.get(KUBERNETES_EXECUTOR_POD_DELETION_COST).isEmpty) { @@ -184,13 +188,20 @@ private[spark] class KubernetesClusterManager extends ExternalClusterManager wit classOf[SparkConf], classOf[org.apache.spark.SecurityManager], classOf[KubernetesExecutorBuilder], classOf[KubernetesClient], classOf[ExecutorPodsSnapshotsStore], classOf[Clock]) - cstr.newInstance( + val allocatorInstance = cstr.newInstance( sc.conf, sc.env.securityManager, new KubernetesExecutorBuilder(), kubernetesClient, snapshotsStore, - new SystemClock()) + new SystemClock()).asInstanceOf[AbstractPodsAllocator] + + // Set the lifecycle manager if provided + lifecycleManager.foreach { manager => + allocatorInstance.setExecutorPodsLifecycleManager(manager) + } + + allocatorInstance } override def initialize(scheduler: TaskScheduler, backend: SchedulerBackend): Unit = { diff --git a/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocatorSuite.scala b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocatorSuite.scala index e994ccbed9a65..fcdf248b2a22c 100644 --- a/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocatorSuite.scala +++ b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocatorSuite.scala @@ -112,6 +112,9 @@ class ExecutorPodsAllocatorSuite extends SparkFunSuite with BeforeAndAfter { @Mock private var schedulerBackend: KubernetesClusterSchedulerBackend = _ + @Mock + private var lifecycleManager: ExecutorPodsLifecycleManager = _ + private var snapshotsStore: DeterministicExecutorPodsSnapshotsStore = _ private var podsAllocatorUnderTest: ExecutorPodsAllocator = _ @@ -142,6 +145,7 @@ class ExecutorPodsAllocatorSuite extends SparkFunSuite with BeforeAndAfter { waitForExecutorPodsClock = new ManualClock(0L) podsAllocatorUnderTest = new ExecutorPodsAllocator( conf, secMgr, executorBuilder, kubernetesClient, snapshotsStore, waitForExecutorPodsClock) + podsAllocatorUnderTest.setExecutorPodsLifecycleManager(lifecycleManager) when(schedulerBackend.getExecutorIds()).thenReturn(Seq.empty) podsAllocatorUnderTest.start(TEST_SPARK_APP_ID, schedulerBackend) when(kubernetesClient.persistentVolumeClaims()).thenReturn(persistentVolumeClaims) @@ -202,6 +206,7 @@ class ExecutorPodsAllocatorSuite extends SparkFunSuite with BeforeAndAfter { val confWithLowMaxPendingPods = conf.clone.set(KUBERNETES_MAX_PENDING_PODS.key, "3") podsAllocatorUnderTest = new ExecutorPodsAllocator(confWithLowMaxPendingPods, secMgr, executorBuilder, kubernetesClient, snapshotsStore, waitForExecutorPodsClock) + podsAllocatorUnderTest.setExecutorPodsLifecycleManager(lifecycleManager) podsAllocatorUnderTest.start(TEST_SPARK_APP_ID, schedulerBackend) podsAllocatorUnderTest.setTotalExpectedExecutors(Map(defaultProfile -> 2, rp -> 3)) @@ -268,6 +273,7 @@ class ExecutorPodsAllocatorSuite extends SparkFunSuite with BeforeAndAfter { .set(KUBERNETES_MAX_PENDING_PODS_PER_RPID.key, "2") podsAllocatorUnderTest = new ExecutorPodsAllocator(confWithLowMaxPendingPodsPerRpId, secMgr, executorBuilder, kubernetesClient, snapshotsStore, waitForExecutorPodsClock) + podsAllocatorUnderTest.setExecutorPodsLifecycleManager(lifecycleManager) podsAllocatorUnderTest.start(TEST_SPARK_APP_ID, schedulerBackend) // Request more than the max per rp for one rp @@ -321,6 +327,7 @@ class ExecutorPodsAllocatorSuite extends SparkFunSuite with BeforeAndAfter { val confWithAllocationMaximum = conf.clone.set(KUBERNETES_ALLOCATION_MAXIMUM.key, "1") podsAllocatorUnderTest = new ExecutorPodsAllocator(confWithAllocationMaximum, secMgr, executorBuilder, kubernetesClient, snapshotsStore, waitForExecutorPodsClock) + podsAllocatorUnderTest.setExecutorPodsLifecycleManager(lifecycleManager) podsAllocatorUnderTest.start(TEST_SPARK_APP_ID, schedulerBackend) val counter = PrivateMethod[AtomicInteger](Symbol("EXECUTOR_ID_COUNTER"))() @@ -838,6 +845,7 @@ class ExecutorPodsAllocatorSuite extends SparkFunSuite with BeforeAndAfter { podsAllocatorUnderTest = new ExecutorPodsAllocator( confWithPVC, secMgr, executorBuilder, kubernetesClient, snapshotsStore, waitForExecutorPodsClock) + podsAllocatorUnderTest.setExecutorPodsLifecycleManager(lifecycleManager) podsAllocatorUnderTest.start(TEST_SPARK_APP_ID, schedulerBackend) when(podsWithNamespace @@ -936,6 +944,7 @@ class ExecutorPodsAllocatorSuite extends SparkFunSuite with BeforeAndAfter { podsAllocatorUnderTest = new ExecutorPodsAllocator( confWithPVC, secMgr, executorBuilder, kubernetesClient, snapshotsStore, waitForExecutorPodsClock) + podsAllocatorUnderTest.setExecutorPodsLifecycleManager(lifecycleManager) podsAllocatorUnderTest.start(TEST_SPARK_APP_ID, schedulerBackend) when(podsWithNamespace @@ -1005,6 +1014,7 @@ class ExecutorPodsAllocatorSuite extends SparkFunSuite with BeforeAndAfter { podsAllocatorUnderTest = new ExecutorPodsAllocator( confWithPVC, secMgr, executorBuilder, kubernetesClient, snapshotsStore, waitForExecutorPodsClock) + podsAllocatorUnderTest.setExecutorPodsLifecycleManager(lifecycleManager) podsAllocatorUnderTest.start(TEST_SPARK_APP_ID, schedulerBackend) val startTime = Instant.now.toEpochMilli @@ -1052,4 +1062,22 @@ class ExecutorPodsAllocatorSuite extends SparkFunSuite with BeforeAndAfter { KubernetesExecutorSpec(executorPodWithId(k8sConf.executorId.toInt, k8sConf.resourceProfileId.toInt), Seq.empty) } + + test("SPARK-55075: Pod creation failures are tracked by ExecutorFailureTracker") { + // Make all pod creation attempts fail + when(podResource.create()).thenThrow(new KubernetesClientException("Simulated pod" + + " creation failure")) + + // Request 3 executors + podsAllocatorUnderTest.setTotalExpectedExecutors(Map(defaultProfile -> 3)) + + // Verify that pod creation was attempted 3 times (once per executor, no retries) + verify(podResource, times(3)).create() + + // Verify that registerPodCreationFailure was called 3 times (once per failed executor) + verify(lifecycleManager, times(3)).registerExecutorFailure() + + // Verify no pods were created since all attempts failed + assert(podsAllocatorUnderTest.invokePrivate(numOutstandingPods).get() == 0) + } } From ec35791b3d987fed2f7b2a872fbbbaf30ada20d5 Mon Sep 17 00:00:00 2001 From: ilicmarkodb Date: Tue, 24 Feb 2026 13:24:27 +0800 Subject: [PATCH 006/130] [SPARK-55647][SQL] Fix `ConstantPropagation` incorrectly replacing attributes with non-binary-stable collations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? * `ConstantPropagation` optimizer rule substitutes attributes with literals derived from equality predicates (e.g. `c = 'hello'`), then propagates them into other conditions in the same conjunction. This is unsafe for non-binary-stable collations (e.g. `UTF8_LCASE`) where equality is non-identity: `c = 'hello'` (case-insensitive) does not imply `c` holds exactly the bytes `'hello'` - it could also be `'HELLO'`, `'Hello'`, etc. * Substituting `c → 'hello'` in a second condition like `c = 'HELLO' COLLATE UNICODE` turns it into the constant expression `'hello' = 'HELLO' COLLATE UNICODE`, which is always `false`, producing incorrect results. * Fixed by guarding `safeToReplace` with `isBinaryStable(ar.dataType)` so propagation is skipped for attributes whose type is not binary-stable. ### Why are the changes needed? Bug fix. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? New unit test. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54435 from ilicmarkodb/fix_collation_. Authored-by: ilicmarkodb Signed-off-by: Wenchen Fan --- .../spark/sql/catalyst/optimizer/expressions.scala | 12 +++++++++++- .../apache/spark/sql/collation/CollationSuite.scala | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/expressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/expressions.scala index 95969a947582a..e406c51e7f8a2 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/expressions.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/expressions.scala @@ -32,6 +32,7 @@ import org.apache.spark.sql.catalyst.rules._ import org.apache.spark.sql.catalyst.trees.{AlwaysProcess, TreeNodeTag} import org.apache.spark.sql.catalyst.trees.TreePattern._ import org.apache.spark.sql.catalyst.util.CharVarcharUtils.CHAR_VARCHAR_TYPE_STRING_METADATA_KEY +import org.apache.spark.sql.catalyst.util.UnsafeRowUtils.isBinaryStable import org.apache.spark.sql.internal.SQLConf import org.apache.spark.sql.types._ import org.apache.spark.unsafe.types.UTF8String @@ -217,8 +218,17 @@ object ConstantPropagation extends Rule[LogicalPlan] { // substituted into `1 + 1 = 1` if 'c' isn't nullable. If 'c' is nullable then the enclosing // NOT prevents us to do the substitution as NOT flips the context (`nullIsFalse`) of what a // null result of the enclosed expression means. + // + // Also, we shouldn't replace attributes with non-binary-stable data types, since this can lead + // to incorrect results. For example: + // `CREATE TABLE t (c STRING COLLATE UTF8_LCASE);` + // `INSERT INTO t VALUES ('HELLO'), ('hello');` + // `SELECT * FROM t WHERE c = 'hello' AND c = 'HELLO' COLLATE UNICODE;` + // If we replace `c` with `'hello'`, we get `'hello' = 'HELLO' COLLATE UNICODE` for the right + // condition, which is false, while the original `c = 'HELLO' COLLATE UNICODE` is true for + // 'HELLO' and false for 'hello'. private def safeToReplace(ar: AttributeReference, nullIsFalse: Boolean) = - !ar.nullable || nullIsFalse + (!ar.nullable || nullIsFalse) && isBinaryStable(ar.dataType) private def replaceConstants( condition: Expression, diff --git a/sql/core/src/test/scala/org/apache/spark/sql/collation/CollationSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/collation/CollationSuite.scala index 4a6e4278dcebb..734c1166c4037 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/collation/CollationSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/collation/CollationSuite.scala @@ -2248,4 +2248,17 @@ class CollationSuite extends DatasourceV2SQLBase with AdaptiveSparkPlanHelper { Seq()) } } + + test("ConstantPropagation does not replace attributes with non-binary-stable collation") { + val tableName = "t1" + withTable(tableName) { + sql(s"CREATE TABLE $tableName (c STRING COLLATE UTF8_LCASE)") + sql(s"INSERT INTO $tableName VALUES ('hello'), ('HELLO')") + + checkAnswer( + sql(s"SELECT * FROM $tableName WHERE c = 'hello' AND c = 'HELLO' COLLATE UNICODE"), + Row("HELLO") + ) + } + } } From 7d67ff3e58fee04f831db2606c14efbdeac2c0ed Mon Sep 17 00:00:00 2001 From: Kent Yao Date: Tue, 24 Feb 2026 17:58:41 +0800 Subject: [PATCH 007/130] [SPARK-55654][SQL] Enable TreePattern pruning for EliminateSubqueryAliases and ResolveInlineTables ### What changes were proposed in this pull request? Replace `AlwaysProcess.fn` with pattern-based pruning in two Analyzer rules: 1. **EliminateSubqueryAliases**: Use `_.containsPattern(SUBQUERY_ALIAS)` - Skips entire plan traversal when no `SubqueryAlias` nodes exist - Common in resolved plans after initial resolution passes 2. **ResolveInlineTables**: Use `_.containsPattern(INLINE_TABLE_EVAL)` - Skips traversal when no `UnresolvedInlineTable` nodes exist - Inline tables are rare; most queries never contain them Also adds `INLINE_TABLE_EVAL` to `UnresolvedInlineTable.nodePatterns`, which was previously only defined on `ResolvedInlineTable`. Without this, the pruning condition for `ResolveInlineTables` could never be satisfied for unresolved inline tables. Both rules previously used `AlwaysProcess.fn`, forcing full tree traversal on every fixedPoint iteration even when no matching nodes existed. TreePatternBits propagation enables O(1) root-level short-circuit. ### Why are the changes needed? Performance optimization: avoids unnecessary full-plan traversals during analysis when the relevant node types are absent. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Existing tests: `AnalysisSuite`, `EliminateSubqueryAliasesSuite`, and inline table related tests all pass. ### Was this patch authored or co-authored using generative AI tooling? Yes, GitHub Copilot. Closes #54440 from yaooqinn/tree-pattern-pruning-inline-tables. Authored-by: Kent Yao Signed-off-by: Kent Yao --- .../org/apache/spark/sql/catalyst/analysis/Analyzer.scala | 2 +- .../spark/sql/catalyst/analysis/ResolveInlineTables.scala | 4 ++-- .../org/apache/spark/sql/catalyst/analysis/unresolved.scala | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala index 0cddb847c349a..04bad39a88baf 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala @@ -3952,7 +3952,7 @@ object EliminateSubqueryAliases extends Rule[LogicalPlan] { // This is also called in the beginning of the optimization phase, and as a result // is using transformUp rather than resolveOperators. def apply(plan: LogicalPlan): LogicalPlan = AnalysisHelper.allowInvokingTransformsInAnalyzer { - plan.transformUpWithPruning(AlwaysProcess.fn, ruleId) { + plan.transformUpWithPruning(_.containsPattern(SUBQUERY_ALIAS), ruleId) { case SubqueryAlias(_, child) => child } } diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveInlineTables.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveInlineTables.scala index 08cb70ddd5dba..82615354c9c3f 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveInlineTables.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveInlineTables.scala @@ -20,7 +20,7 @@ package org.apache.spark.sql.catalyst.analysis import org.apache.spark.sql.catalyst.expressions.EvalHelper import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan import org.apache.spark.sql.catalyst.rules.Rule -import org.apache.spark.sql.catalyst.trees.AlwaysProcess +import org.apache.spark.sql.catalyst.trees.TreePattern.INLINE_TABLE_EVAL import org.apache.spark.sql.catalyst.util.EvaluateUnresolvedInlineTable /** @@ -28,7 +28,7 @@ import org.apache.spark.sql.catalyst.util.EvaluateUnresolvedInlineTable */ object ResolveInlineTables extends Rule[LogicalPlan] with EvalHelper { override def apply(plan: LogicalPlan): LogicalPlan = { - plan.resolveOperatorsWithPruning(AlwaysProcess.fn, ruleId) { + plan.resolveOperatorsWithPruning(_.containsPattern(INLINE_TABLE_EVAL), ruleId) { case table: UnresolvedInlineTable if table.expressionsResolved => EvaluateUnresolvedInlineTable.evaluateUnresolvedInlineTable(table) } diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/unresolved.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/unresolved.scala index fffbc7511a1de..5726c573ee7d8 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/unresolved.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/unresolved.scala @@ -178,6 +178,8 @@ case class UnresolvedInlineTable( rows: Seq[Seq[Expression]]) extends UnresolvedLeafNode { + final override val nodePatterns: Seq[TreePattern] = Seq(INLINE_TABLE_EVAL) + lazy val expressionsResolved: Boolean = rows.forall(_.forall(_.resolved)) } From 1e1b3635cbefa426e39ccf91581b4e7a1cc4712d Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Tue, 24 Feb 2026 07:02:27 -0800 Subject: [PATCH 008/130] [SPARK-55653][K8S] Support `NetworkPolicy` for Spark executor pods ### What changes were proposed in this pull request? This PR aims to support `NetworkPolicy` for Spark executor pods. ### Why are the changes needed? `NetworkPolicy` is frequently used in the production to isolate Spark applications. - https://kubernetes.io/docs/concepts/services-networking/network-policies/ ### Does this PR introduce _any_ user-facing change? This is a security feature to make Spark K8s executor pods access only from the pods with the same application ID. There are two ways if a user wants to access the executor pods from outside. 1. Use a pod with the same application ID with the target Spark applications. 2. Submit a Spark job with the following configuration. ``` spark.kubernetes.driver.pod.excludedFeatureSteps=org.apache.spark.deploy.k8s.features.NetworkPolicyFeatureStep ``` ### How was this patch tested? Pass the CIs with the newly added test suite. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54442 from dongjoon-hyun/SPARK-55653. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- docs/core-migration-guide.md | 2 + .../features/NetworkPolicyFeatureStep.scala | 60 +++++++++++++++++++ .../k8s/submit/KubernetesDriverBuilder.scala | 1 + .../NetworkPolicyFeatureStepSuite.scala | 60 +++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/NetworkPolicyFeatureStep.scala create mode 100644 resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/features/NetworkPolicyFeatureStepSuite.scala diff --git a/docs/core-migration-guide.md b/docs/core-migration-guide.md index 63945c5aadc0d..b44a2a4ddd0e6 100644 --- a/docs/core-migration-guide.md +++ b/docs/core-migration-guide.md @@ -26,6 +26,8 @@ license: | - Since Spark 4.2, Spark will allocate executor pods with a batch size of `20`. To restore the legacy behavior, you can set `spark.kubernetes.allocation.batch.size` to `10`. +- Since Spark 4.2, Spark configures a `NetworkPolicy` by default so that executor pods only accept ingress traffic from the driver and peer executors within the same job. To disable this and restore the legacy behavior, set `spark.kubernetes.driver.pod.excludedFeatureSteps` to `org.apache.spark.deploy.k8s.features.NetworkPolicyFeatureStep`. + ## Upgrading from Core 4.0 to 4.1 - Since Spark 4.1, Spark Master daemon provides REST API by default. To restore the behavior before Spark 4.1, you can set `spark.master.rest.enabled` to `false`. diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/NetworkPolicyFeatureStep.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/NetworkPolicyFeatureStep.scala new file mode 100644 index 0000000000000..e6d53ca9438fc --- /dev/null +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/NetworkPolicyFeatureStep.scala @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.spark.deploy.k8s.features + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicyBuilder + +import org.apache.spark.deploy.k8s.{KubernetesDriverConf, SparkPod} +import org.apache.spark.deploy.k8s.Constants._ + +/** + * A feature step that configures a NetworkPolicy for Spark executors. + * It restricts ingress traffic to executors so that they only accept connections + * from the driver and other executors within the same Spark application. + */ +private[spark] class NetworkPolicyFeatureStep(conf: KubernetesDriverConf) + extends KubernetesFeatureConfigStep { + private val policyName = conf.resourceNamePrefix + "-policy" + + override def configurePod(pod: SparkPod): SparkPod = pod + + override def getAdditionalKubernetesResources(): Seq[HasMetadata] = { + val appId = conf.appId + val policy = new NetworkPolicyBuilder() + .withNewMetadata() + .withName(policyName) + .withNamespace(conf.namespace) + .addToLabels(SPARK_APP_ID_LABEL, appId) + .endMetadata() + .withNewSpec() + .withNewPodSelector() + .addToMatchLabels(SPARK_ROLE_LABEL, SPARK_POD_EXECUTOR_ROLE) + .addToMatchLabels(SPARK_APP_ID_LABEL, appId) + .endPodSelector() + .addNewIngress() + .addNewFrom() + .withNewPodSelector() + .addToMatchLabels(SPARK_APP_ID_LABEL, appId) + .endPodSelector() + .endFrom() + .endIngress() + .endSpec() + .build(); + Seq(policy) + } +} diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/submit/KubernetesDriverBuilder.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/submit/KubernetesDriverBuilder.scala index da234762ea1de..f50051de737d7 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/submit/KubernetesDriverBuilder.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/submit/KubernetesDriverBuilder.scala @@ -76,6 +76,7 @@ class KubernetesDriverBuilder { new BasicDriverFeatureStep(conf), new DriverKubernetesCredentialsFeatureStep(conf), new DriverServiceFeatureStep(conf), + new NetworkPolicyFeatureStep(conf), new MountSecretsFeatureStep(conf), new EnvSecretsFeatureStep(conf), new MountVolumesFeatureStep(conf), diff --git a/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/features/NetworkPolicyFeatureStepSuite.scala b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/features/NetworkPolicyFeatureStepSuite.scala new file mode 100644 index 0000000000000..f75969ded30b4 --- /dev/null +++ b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/features/NetworkPolicyFeatureStepSuite.scala @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.spark.deploy.k8s.features + +import scala.jdk.CollectionConverters._ + +import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicy + +import org.apache.spark.{SparkConf, SparkFunSuite} +import org.apache.spark.deploy.k8s.{KubernetesTestConf, SparkPod} +import org.apache.spark.deploy.k8s.Constants._ + +class NetworkPolicyFeatureStepSuite extends SparkFunSuite { + + test("NetworkPolicy creation") { + val conf = KubernetesTestConf.createDriverConf(sparkConf = new SparkConf(false)) + val step = new NetworkPolicyFeatureStep(conf) + + // configures pod identically + val pod = SparkPod.initialPod() + assert(step.configurePod(pod) === pod) + + // additional pod system properties is empty + assert(step.getAdditionalPodSystemProperties().isEmpty) + + // Check additional resources + val resources = step.getAdditionalKubernetesResources() + assert(resources.size === 1) + + val policy = resources.head.asInstanceOf[NetworkPolicy] + assert(policy.getMetadata.getName === s"${conf.resourceNamePrefix}-policy") + assert(policy.getMetadata.getNamespace === conf.namespace) + assert(policy.getMetadata.getLabels.get(SPARK_APP_ID_LABEL) === conf.appId) + + val labels = policy.getSpec.getPodSelector.getMatchLabels + assert(labels.get(SPARK_ROLE_LABEL) === SPARK_POD_EXECUTOR_ROLE) + assert(labels.get(SPARK_APP_ID_LABEL) === conf.appId) + + val ingress = policy.getSpec.getIngress.asScala + assert(ingress.size === 1) + + val from = ingress.head.getFrom.asScala + assert(from.size === 1) + assert(from.head.getPodSelector.getMatchLabels.get(SPARK_APP_ID_LABEL) === conf.appId) + } +} From a5316a42528252b34f6ea3321d826ffd3bbb9b89 Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Tue, 24 Feb 2026 07:10:21 -0800 Subject: [PATCH 009/130] [SPARK-55655][MLLIB] Make `CountVectorizer` vocabulary deterministic when counts are equal ### What changes were proposed in this pull request? This pr fix `CountVectorizer` to use a deterministic ordering when selecting the top vocabulary terms. Specifically, when two terms have the same frequency (count), they are now sorted by the term itself (lexicographically) as a tie-breaker. ### Why are the changes needed? Currently, `CountVectorizer` uses `wordCounts.top(...)(Ordering.by(_._2))` to select the vocabulary. This comparison only considers term counts. When multiple terms have the same count, the resulting order in the vocabulary is non-deterministic and depends on the RDD partition processing order or the iteration order of the internal hash maps. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? - Pass Github Actions - Added a new test case in `CountVectorizerSuite` that intentionally creates a dataset with tied term counts and asserts a specific, deterministic vocabulary order. ### Was this patch authored or co-authored using generative AI tooling? No Closes #54446 from LuciferYang/SPARK-55655. Authored-by: yangjie01 Signed-off-by: Dongjoon Hyun --- .../apache/spark/ml/feature/CountVectorizer.scala | 5 ++++- .../spark/ml/feature/CountVectorizerSuite.scala | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mllib/src/main/scala/org/apache/spark/ml/feature/CountVectorizer.scala b/mllib/src/main/scala/org/apache/spark/ml/feature/CountVectorizer.scala index 060e445e02548..c7fc4ce6898bd 100644 --- a/mllib/src/main/scala/org/apache/spark/ml/feature/CountVectorizer.scala +++ b/mllib/src/main/scala/org/apache/spark/ml/feature/CountVectorizer.scala @@ -235,8 +235,11 @@ class CountVectorizer @Since("1.5.0") (@Since("1.5.0") override val uid: String) val fullVocabSize = wordCounts.count() + val ordering = Ordering.Tuple2(Ordering.Long, Ordering.String.reverse) + .on[(String, Long)] { case (word, count) => (count, word) } + val vocab = wordCounts - .top(math.min(fullVocabSize, vocSize).toInt)(Ordering.by(_._2)) + .top(math.min(fullVocabSize, vocSize).toInt)(ordering) .map(_._1) if (input.getStorageLevel != StorageLevel.NONE) { diff --git a/mllib/src/test/scala/org/apache/spark/ml/feature/CountVectorizerSuite.scala b/mllib/src/test/scala/org/apache/spark/ml/feature/CountVectorizerSuite.scala index 431772006c820..ecde4e92a34f7 100644 --- a/mllib/src/test/scala/org/apache/spark/ml/feature/CountVectorizerSuite.scala +++ b/mllib/src/test/scala/org/apache/spark/ml/feature/CountVectorizerSuite.scala @@ -350,4 +350,18 @@ class CountVectorizerSuite extends MLTest with DefaultReadWriteTest { assert(features === Vectors.sparse(0, Seq())) } } + + test("SPARK-55655: CountVectorizer vocabulary ordering is deterministic for tied counts") { + val df = Seq( + (0, split("a b c d e")), + (1, split("e d c b a")) + ).toDF("id", "words") + + val cvModel = new CountVectorizer() + .setInputCol("words") + .setOutputCol("features") + .fit(df) + + assert(cvModel.vocabulary === Array("a", "b", "c", "d", "e")) + } } From 7da1356837e85c548d8da76c0db8143b3e6f87ab Mon Sep 17 00:00:00 2001 From: Aditya Nambiar Date: Tue, 24 Feb 2026 11:50:34 -0400 Subject: [PATCH 010/130] [SPARK-55264] Add ExecuteOutput command to Spark Connect pipelines proto MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? This pull request adds a new ExecuteOutput command to the Spark Connect pipelines protobuf definition. The new command enables clients to directly execute multiple flows writing to an output. ### Why are the changes needed? Required to enable standlone Python MV/ST ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? ### Was this patch authored or co-authored using generative AI tooling? Closes #54104 from aditya-nambiar/SPARK-55264. Authored-by: Aditya Nambiar Signed-off-by: Herman van Hövell --- .../sql/connect/proto/pipelines_pb2.py | 110 +++++++++--------- .../sql/connect/proto/pipelines_pb2.pyi | 101 ++++++++++++++++ .../protobuf/spark/connect/pipelines.proto | 21 ++++ 3 files changed, 178 insertions(+), 54 deletions(-) diff --git a/python/pyspark/sql/connect/proto/pipelines_pb2.py b/python/pyspark/sql/connect/proto/pipelines_pb2.py index ddd60cf1ac7c9..ebdefc10ec05b 100644 --- a/python/pyspark/sql/connect/proto/pipelines_pb2.py +++ b/python/pyspark/sql/connect/proto/pipelines_pb2.py @@ -42,7 +42,7 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x1dspark/connect/pipelines.proto\x12\rspark.connect\x1a\x19google/protobuf/any.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1aspark/connect/common.proto\x1a\x1dspark/connect/relations.proto\x1a\x19spark/connect/types.proto"\xed"\n\x0fPipelineCommand\x12h\n\x15\x63reate_dataflow_graph\x18\x01 \x01(\x0b\x32\x32.spark.connect.PipelineCommand.CreateDataflowGraphH\x00R\x13\x63reateDataflowGraph\x12R\n\rdefine_output\x18\x02 \x01(\x0b\x32+.spark.connect.PipelineCommand.DefineOutputH\x00R\x0c\x64\x65\x66ineOutput\x12L\n\x0b\x64\x65\x66ine_flow\x18\x03 \x01(\x0b\x32).spark.connect.PipelineCommand.DefineFlowH\x00R\ndefineFlow\x12\x62\n\x13\x64rop_dataflow_graph\x18\x04 \x01(\x0b\x32\x30.spark.connect.PipelineCommand.DropDataflowGraphH\x00R\x11\x64ropDataflowGraph\x12\x46\n\tstart_run\x18\x05 \x01(\x0b\x32\'.spark.connect.PipelineCommand.StartRunH\x00R\x08startRun\x12r\n\x19\x64\x65\x66ine_sql_graph_elements\x18\x06 \x01(\x0b\x32\x35.spark.connect.PipelineCommand.DefineSqlGraphElementsH\x00R\x16\x64\x65\x66ineSqlGraphElements\x12\xa1\x01\n*get_query_function_execution_signal_stream\x18\x07 \x01(\x0b\x32\x44.spark.connect.PipelineCommand.GetQueryFunctionExecutionSignalStreamH\x00R%getQueryFunctionExecutionSignalStream\x12\x88\x01\n!define_flow_query_function_result\x18\x08 \x01(\x0b\x32<.spark.connect.PipelineCommand.DefineFlowQueryFunctionResultH\x00R\x1d\x64\x65\x66ineFlowQueryFunctionResult\x12\x35\n\textension\x18\xe7\x07 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\textension\x1a\xb4\x02\n\x13\x43reateDataflowGraph\x12,\n\x0f\x64\x65\x66\x61ult_catalog\x18\x01 \x01(\tH\x00R\x0e\x64\x65\x66\x61ultCatalog\x88\x01\x01\x12.\n\x10\x64\x65\x66\x61ult_database\x18\x02 \x01(\tH\x01R\x0f\x64\x65\x66\x61ultDatabase\x88\x01\x01\x12Z\n\x08sql_conf\x18\x05 \x03(\x0b\x32?.spark.connect.PipelineCommand.CreateDataflowGraph.SqlConfEntryR\x07sqlConf\x1a:\n\x0cSqlConfEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\x12\n\x10_default_catalogB\x13\n\x11_default_database\x1aZ\n\x11\x44ropDataflowGraph\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x42\x14\n\x12_dataflow_graph_id\x1a\x92\n\n\x0c\x44\x65\x66ineOutput\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x01R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12$\n\x0boutput_name\x18\x02 \x01(\tH\x02R\noutputName\x88\x01\x01\x12?\n\x0boutput_type\x18\x03 \x01(\x0e\x32\x19.spark.connect.OutputTypeH\x03R\noutputType\x88\x01\x01\x12\x1d\n\x07\x63omment\x18\x04 \x01(\tH\x04R\x07\x63omment\x88\x01\x01\x12X\n\x14source_code_location\x18\x05 \x01(\x0b\x32!.spark.connect.SourceCodeLocationH\x05R\x12sourceCodeLocation\x88\x01\x01\x12_\n\rtable_details\x18\x06 \x01(\x0b\x32\x38.spark.connect.PipelineCommand.DefineOutput.TableDetailsH\x00R\x0ctableDetails\x12\\\n\x0csink_details\x18\x07 \x01(\x0b\x32\x37.spark.connect.PipelineCommand.DefineOutput.SinkDetailsH\x00R\x0bsinkDetails\x12\x35\n\textension\x18\xe7\x07 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\textension\x1a\xc0\x03\n\x0cTableDetails\x12x\n\x10table_properties\x18\x01 \x03(\x0b\x32M.spark.connect.PipelineCommand.DefineOutput.TableDetails.TablePropertiesEntryR\x0ftableProperties\x12%\n\x0epartition_cols\x18\x02 \x03(\tR\rpartitionCols\x12\x1b\n\x06\x66ormat\x18\x03 \x01(\tH\x01R\x06\x66ormat\x88\x01\x01\x12\x43\n\x10schema_data_type\x18\x04 \x01(\x0b\x32\x17.spark.connect.DataTypeH\x00R\x0eschemaDataType\x12%\n\rschema_string\x18\x05 \x01(\tH\x00R\x0cschemaString\x12-\n\x12\x63lustering_columns\x18\x06 \x03(\tR\x11\x63lusteringColumns\x1a\x42\n\x14TablePropertiesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\x08\n\x06schemaB\t\n\x07_format\x1a\xd1\x01\n\x0bSinkDetails\x12^\n\x07options\x18\x01 \x03(\x0b\x32\x44.spark.connect.PipelineCommand.DefineOutput.SinkDetails.OptionsEntryR\x07options\x12\x1b\n\x06\x66ormat\x18\x02 \x01(\tH\x00R\x06\x66ormat\x88\x01\x01\x1a:\n\x0cOptionsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\t\n\x07_formatB\t\n\x07\x64\x65tailsB\x14\n\x12_dataflow_graph_idB\x0e\n\x0c_output_nameB\x0e\n\x0c_output_typeB\n\n\x08_commentB\x17\n\x15_source_code_location\x1a\xff\x06\n\nDefineFlow\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x01R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12 \n\tflow_name\x18\x02 \x01(\tH\x02R\x08\x66lowName\x88\x01\x01\x12\x33\n\x13target_dataset_name\x18\x03 \x01(\tH\x03R\x11targetDatasetName\x88\x01\x01\x12Q\n\x08sql_conf\x18\x04 \x03(\x0b\x32\x36.spark.connect.PipelineCommand.DefineFlow.SqlConfEntryR\x07sqlConf\x12 \n\tclient_id\x18\x05 \x01(\tH\x04R\x08\x63lientId\x88\x01\x01\x12X\n\x14source_code_location\x18\x06 \x01(\x0b\x32!.spark.connect.SourceCodeLocationH\x05R\x12sourceCodeLocation\x88\x01\x01\x12x\n\x15relation_flow_details\x18\x07 \x01(\x0b\x32\x42.spark.connect.PipelineCommand.DefineFlow.WriteRelationFlowDetailsH\x00R\x13relationFlowDetails\x12\x35\n\textension\x18\xe7\x07 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\textension\x12\x17\n\x04once\x18\x08 \x01(\x08H\x06R\x04once\x88\x01\x01\x1a:\n\x0cSqlConfEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x1a\x61\n\x18WriteRelationFlowDetails\x12\x38\n\x08relation\x18\x01 \x01(\x0b\x32\x17.spark.connect.RelationH\x00R\x08relation\x88\x01\x01\x42\x0b\n\t_relation\x1a:\n\x08Response\x12 \n\tflow_name\x18\x01 \x01(\tH\x00R\x08\x66lowName\x88\x01\x01\x42\x0c\n\n_flow_nameB\t\n\x07\x64\x65tailsB\x14\n\x12_dataflow_graph_idB\x0c\n\n_flow_nameB\x16\n\x14_target_dataset_nameB\x0c\n\n_client_idB\x17\n\x15_source_code_locationB\x07\n\x05_once\x1a\xc2\x02\n\x08StartRun\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12\x34\n\x16\x66ull_refresh_selection\x18\x02 \x03(\tR\x14\x66ullRefreshSelection\x12-\n\x10\x66ull_refresh_all\x18\x03 \x01(\x08H\x01R\x0e\x66ullRefreshAll\x88\x01\x01\x12+\n\x11refresh_selection\x18\x04 \x03(\tR\x10refreshSelection\x12\x15\n\x03\x64ry\x18\x05 \x01(\x08H\x02R\x03\x64ry\x88\x01\x01\x12\x1d\n\x07storage\x18\x06 \x01(\tH\x03R\x07storage\x88\x01\x01\x42\x14\n\x12_dataflow_graph_idB\x13\n\x11_full_refresh_allB\x06\n\x04_dryB\n\n\x08_storage\x1a\xc7\x01\n\x16\x44\x65\x66ineSqlGraphElements\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12\'\n\rsql_file_path\x18\x02 \x01(\tH\x01R\x0bsqlFilePath\x88\x01\x01\x12\x1e\n\x08sql_text\x18\x03 \x01(\tH\x02R\x07sqlText\x88\x01\x01\x42\x14\n\x12_dataflow_graph_idB\x10\n\x0e_sql_file_pathB\x0b\n\t_sql_text\x1a\x9e\x01\n%GetQueryFunctionExecutionSignalStream\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12 \n\tclient_id\x18\x02 \x01(\tH\x01R\x08\x63lientId\x88\x01\x01\x42\x14\n\x12_dataflow_graph_idB\x0c\n\n_client_id\x1a\xdd\x01\n\x1d\x44\x65\x66ineFlowQueryFunctionResult\x12 \n\tflow_name\x18\x01 \x01(\tH\x00R\x08\x66lowName\x88\x01\x01\x12/\n\x11\x64\x61taflow_graph_id\x18\x02 \x01(\tH\x01R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12\x38\n\x08relation\x18\x03 \x01(\x0b\x32\x17.spark.connect.RelationH\x02R\x08relation\x88\x01\x01\x42\x0c\n\n_flow_nameB\x14\n\x12_dataflow_graph_idB\x0b\n\t_relationB\x0e\n\x0c\x63ommand_type"\xf0\x05\n\x15PipelineCommandResult\x12\x81\x01\n\x1c\x63reate_dataflow_graph_result\x18\x01 \x01(\x0b\x32>.spark.connect.PipelineCommandResult.CreateDataflowGraphResultH\x00R\x19\x63reateDataflowGraphResult\x12k\n\x14\x64\x65\x66ine_output_result\x18\x02 \x01(\x0b\x32\x37.spark.connect.PipelineCommandResult.DefineOutputResultH\x00R\x12\x64\x65\x66ineOutputResult\x12\x65\n\x12\x64\x65\x66ine_flow_result\x18\x03 \x01(\x0b\x32\x35.spark.connect.PipelineCommandResult.DefineFlowResultH\x00R\x10\x64\x65\x66ineFlowResult\x1a\x62\n\x19\x43reateDataflowGraphResult\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x42\x14\n\x12_dataflow_graph_id\x1a\x85\x01\n\x12\x44\x65\x66ineOutputResult\x12W\n\x13resolved_identifier\x18\x01 \x01(\x0b\x32!.spark.connect.ResolvedIdentifierH\x00R\x12resolvedIdentifier\x88\x01\x01\x42\x16\n\x14_resolved_identifier\x1a\x83\x01\n\x10\x44\x65\x66ineFlowResult\x12W\n\x13resolved_identifier\x18\x01 \x01(\x0b\x32!.spark.connect.ResolvedIdentifierH\x00R\x12resolvedIdentifier\x88\x01\x01\x42\x16\n\x14_resolved_identifierB\r\n\x0bresult_type"I\n\x13PipelineEventResult\x12\x32\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x1c.spark.connect.PipelineEventR\x05\x65vent"t\n\rPipelineEvent\x12\x38\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\ttimestamp\x12\x1d\n\x07message\x18\x02 \x01(\tH\x00R\x07message\x88\x01\x01\x42\n\n\x08_message"\xf1\x01\n\x12SourceCodeLocation\x12 \n\tfile_name\x18\x01 \x01(\tH\x00R\x08\x66ileName\x88\x01\x01\x12$\n\x0bline_number\x18\x02 \x01(\x05H\x01R\nlineNumber\x88\x01\x01\x12,\n\x0f\x64\x65\x66inition_path\x18\x03 \x01(\tH\x02R\x0e\x64\x65\x66initionPath\x88\x01\x01\x12\x33\n\textension\x18\xe7\x07 \x03(\x0b\x32\x14.google.protobuf.AnyR\textensionB\x0c\n\n_file_nameB\x0e\n\x0c_line_numberB\x12\n\x10_definition_path"E\n$PipelineQueryFunctionExecutionSignal\x12\x1d\n\nflow_names\x18\x01 \x03(\tR\tflowNames"\x87\x02\n\x17PipelineAnalysisContext\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12,\n\x0f\x64\x65\x66inition_path\x18\x02 \x01(\tH\x01R\x0e\x64\x65\x66initionPath\x88\x01\x01\x12 \n\tflow_name\x18\x03 \x01(\tH\x02R\x08\x66lowName\x88\x01\x01\x12\x33\n\textension\x18\xe7\x07 \x03(\x0b\x32\x14.google.protobuf.AnyR\textensionB\x14\n\x12_dataflow_graph_idB\x12\n\x10_definition_pathB\x0c\n\n_flow_name*i\n\nOutputType\x12\x1b\n\x17OUTPUT_TYPE_UNSPECIFIED\x10\x00\x12\x15\n\x11MATERIALIZED_VIEW\x10\x01\x12\t\n\x05TABLE\x10\x02\x12\x12\n\x0eTEMPORARY_VIEW\x10\x03\x12\x08\n\x04SINK\x10\x04\x42\x36\n\x1eorg.apache.spark.connect.protoP\x01Z\x12internal/generatedb\x06proto3' + b'\n\x1dspark/connect/pipelines.proto\x12\rspark.connect\x1a\x19google/protobuf/any.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1aspark/connect/common.proto\x1a\x1dspark/connect/relations.proto\x1a\x19spark/connect/types.proto"\xbb&\n\x0fPipelineCommand\x12h\n\x15\x63reate_dataflow_graph\x18\x01 \x01(\x0b\x32\x32.spark.connect.PipelineCommand.CreateDataflowGraphH\x00R\x13\x63reateDataflowGraph\x12R\n\rdefine_output\x18\x02 \x01(\x0b\x32+.spark.connect.PipelineCommand.DefineOutputH\x00R\x0c\x64\x65\x66ineOutput\x12L\n\x0b\x64\x65\x66ine_flow\x18\x03 \x01(\x0b\x32).spark.connect.PipelineCommand.DefineFlowH\x00R\ndefineFlow\x12\x62\n\x13\x64rop_dataflow_graph\x18\x04 \x01(\x0b\x32\x30.spark.connect.PipelineCommand.DropDataflowGraphH\x00R\x11\x64ropDataflowGraph\x12\x46\n\tstart_run\x18\x05 \x01(\x0b\x32\'.spark.connect.PipelineCommand.StartRunH\x00R\x08startRun\x12r\n\x19\x64\x65\x66ine_sql_graph_elements\x18\x06 \x01(\x0b\x32\x35.spark.connect.PipelineCommand.DefineSqlGraphElementsH\x00R\x16\x64\x65\x66ineSqlGraphElements\x12\xa1\x01\n*get_query_function_execution_signal_stream\x18\x07 \x01(\x0b\x32\x44.spark.connect.PipelineCommand.GetQueryFunctionExecutionSignalStreamH\x00R%getQueryFunctionExecutionSignalStream\x12\x88\x01\n!define_flow_query_function_result\x18\x08 \x01(\x0b\x32<.spark.connect.PipelineCommand.DefineFlowQueryFunctionResultH\x00R\x1d\x64\x65\x66ineFlowQueryFunctionResult\x12\x65\n\x14\x65xecute_output_flows\x18\t \x01(\x0b\x32\x31.spark.connect.PipelineCommand.ExecuteOutputFlowsH\x00R\x12\x65xecuteOutputFlows\x12\x35\n\textension\x18\xe7\x07 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\textension\x1a\xb4\x02\n\x13\x43reateDataflowGraph\x12,\n\x0f\x64\x65\x66\x61ult_catalog\x18\x01 \x01(\tH\x00R\x0e\x64\x65\x66\x61ultCatalog\x88\x01\x01\x12.\n\x10\x64\x65\x66\x61ult_database\x18\x02 \x01(\tH\x01R\x0f\x64\x65\x66\x61ultDatabase\x88\x01\x01\x12Z\n\x08sql_conf\x18\x05 \x03(\x0b\x32?.spark.connect.PipelineCommand.CreateDataflowGraph.SqlConfEntryR\x07sqlConf\x1a:\n\x0cSqlConfEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\x12\n\x10_default_catalogB\x13\n\x11_default_database\x1aZ\n\x11\x44ropDataflowGraph\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x42\x14\n\x12_dataflow_graph_id\x1a\x92\n\n\x0c\x44\x65\x66ineOutput\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x01R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12$\n\x0boutput_name\x18\x02 \x01(\tH\x02R\noutputName\x88\x01\x01\x12?\n\x0boutput_type\x18\x03 \x01(\x0e\x32\x19.spark.connect.OutputTypeH\x03R\noutputType\x88\x01\x01\x12\x1d\n\x07\x63omment\x18\x04 \x01(\tH\x04R\x07\x63omment\x88\x01\x01\x12X\n\x14source_code_location\x18\x05 \x01(\x0b\x32!.spark.connect.SourceCodeLocationH\x05R\x12sourceCodeLocation\x88\x01\x01\x12_\n\rtable_details\x18\x06 \x01(\x0b\x32\x38.spark.connect.PipelineCommand.DefineOutput.TableDetailsH\x00R\x0ctableDetails\x12\\\n\x0csink_details\x18\x07 \x01(\x0b\x32\x37.spark.connect.PipelineCommand.DefineOutput.SinkDetailsH\x00R\x0bsinkDetails\x12\x35\n\textension\x18\xe7\x07 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\textension\x1a\xc0\x03\n\x0cTableDetails\x12x\n\x10table_properties\x18\x01 \x03(\x0b\x32M.spark.connect.PipelineCommand.DefineOutput.TableDetails.TablePropertiesEntryR\x0ftableProperties\x12%\n\x0epartition_cols\x18\x02 \x03(\tR\rpartitionCols\x12\x1b\n\x06\x66ormat\x18\x03 \x01(\tH\x01R\x06\x66ormat\x88\x01\x01\x12\x43\n\x10schema_data_type\x18\x04 \x01(\x0b\x32\x17.spark.connect.DataTypeH\x00R\x0eschemaDataType\x12%\n\rschema_string\x18\x05 \x01(\tH\x00R\x0cschemaString\x12-\n\x12\x63lustering_columns\x18\x06 \x03(\tR\x11\x63lusteringColumns\x1a\x42\n\x14TablePropertiesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\x08\n\x06schemaB\t\n\x07_format\x1a\xd1\x01\n\x0bSinkDetails\x12^\n\x07options\x18\x01 \x03(\x0b\x32\x44.spark.connect.PipelineCommand.DefineOutput.SinkDetails.OptionsEntryR\x07options\x12\x1b\n\x06\x66ormat\x18\x02 \x01(\tH\x00R\x06\x66ormat\x88\x01\x01\x1a:\n\x0cOptionsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x42\t\n\x07_formatB\t\n\x07\x64\x65tailsB\x14\n\x12_dataflow_graph_idB\x0e\n\x0c_output_nameB\x0e\n\x0c_output_typeB\n\n\x08_commentB\x17\n\x15_source_code_location\x1a\xff\x06\n\nDefineFlow\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x01R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12 \n\tflow_name\x18\x02 \x01(\tH\x02R\x08\x66lowName\x88\x01\x01\x12\x33\n\x13target_dataset_name\x18\x03 \x01(\tH\x03R\x11targetDatasetName\x88\x01\x01\x12Q\n\x08sql_conf\x18\x04 \x03(\x0b\x32\x36.spark.connect.PipelineCommand.DefineFlow.SqlConfEntryR\x07sqlConf\x12 \n\tclient_id\x18\x05 \x01(\tH\x04R\x08\x63lientId\x88\x01\x01\x12X\n\x14source_code_location\x18\x06 \x01(\x0b\x32!.spark.connect.SourceCodeLocationH\x05R\x12sourceCodeLocation\x88\x01\x01\x12x\n\x15relation_flow_details\x18\x07 \x01(\x0b\x32\x42.spark.connect.PipelineCommand.DefineFlow.WriteRelationFlowDetailsH\x00R\x13relationFlowDetails\x12\x35\n\textension\x18\xe7\x07 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\textension\x12\x17\n\x04once\x18\x08 \x01(\x08H\x06R\x04once\x88\x01\x01\x1a:\n\x0cSqlConfEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x1a\x61\n\x18WriteRelationFlowDetails\x12\x38\n\x08relation\x18\x01 \x01(\x0b\x32\x17.spark.connect.RelationH\x00R\x08relation\x88\x01\x01\x42\x0b\n\t_relation\x1a:\n\x08Response\x12 \n\tflow_name\x18\x01 \x01(\tH\x00R\x08\x66lowName\x88\x01\x01\x42\x0c\n\n_flow_nameB\t\n\x07\x64\x65tailsB\x14\n\x12_dataflow_graph_idB\x0c\n\n_flow_nameB\x16\n\x14_target_dataset_nameB\x0c\n\n_client_idB\x17\n\x15_source_code_locationB\x07\n\x05_once\x1a\xe4\x02\n\x12\x45xecuteOutputFlows\x12U\n\rdefine_output\x18\x01 \x01(\x0b\x32+.spark.connect.PipelineCommand.DefineOutputH\x00R\x0c\x64\x65\x66ineOutput\x88\x01\x01\x12L\n\x0c\x64\x65\x66ine_flows\x18\x02 \x03(\x0b\x32).spark.connect.PipelineCommand.DefineFlowR\x0b\x64\x65\x66ineFlows\x12&\n\x0c\x66ull_refresh\x18\x03 \x01(\x08H\x01R\x0b\x66ullRefresh\x88\x01\x01\x12\x1d\n\x07storage\x18\x04 \x01(\tH\x02R\x07storage\x88\x01\x01\x12\x33\n\textension\x18\xe7\x07 \x03(\x0b\x32\x14.google.protobuf.AnyR\textensionB\x10\n\x0e_define_outputB\x0f\n\r_full_refreshB\n\n\x08_storage\x1a\xc2\x02\n\x08StartRun\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12\x34\n\x16\x66ull_refresh_selection\x18\x02 \x03(\tR\x14\x66ullRefreshSelection\x12-\n\x10\x66ull_refresh_all\x18\x03 \x01(\x08H\x01R\x0e\x66ullRefreshAll\x88\x01\x01\x12+\n\x11refresh_selection\x18\x04 \x03(\tR\x10refreshSelection\x12\x15\n\x03\x64ry\x18\x05 \x01(\x08H\x02R\x03\x64ry\x88\x01\x01\x12\x1d\n\x07storage\x18\x06 \x01(\tH\x03R\x07storage\x88\x01\x01\x42\x14\n\x12_dataflow_graph_idB\x13\n\x11_full_refresh_allB\x06\n\x04_dryB\n\n\x08_storage\x1a\xc7\x01\n\x16\x44\x65\x66ineSqlGraphElements\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12\'\n\rsql_file_path\x18\x02 \x01(\tH\x01R\x0bsqlFilePath\x88\x01\x01\x12\x1e\n\x08sql_text\x18\x03 \x01(\tH\x02R\x07sqlText\x88\x01\x01\x42\x14\n\x12_dataflow_graph_idB\x10\n\x0e_sql_file_pathB\x0b\n\t_sql_text\x1a\x9e\x01\n%GetQueryFunctionExecutionSignalStream\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12 \n\tclient_id\x18\x02 \x01(\tH\x01R\x08\x63lientId\x88\x01\x01\x42\x14\n\x12_dataflow_graph_idB\x0c\n\n_client_id\x1a\xdd\x01\n\x1d\x44\x65\x66ineFlowQueryFunctionResult\x12 \n\tflow_name\x18\x01 \x01(\tH\x00R\x08\x66lowName\x88\x01\x01\x12/\n\x11\x64\x61taflow_graph_id\x18\x02 \x01(\tH\x01R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12\x38\n\x08relation\x18\x03 \x01(\x0b\x32\x17.spark.connect.RelationH\x02R\x08relation\x88\x01\x01\x42\x0c\n\n_flow_nameB\x14\n\x12_dataflow_graph_idB\x0b\n\t_relationB\x0e\n\x0c\x63ommand_type"\xf0\x05\n\x15PipelineCommandResult\x12\x81\x01\n\x1c\x63reate_dataflow_graph_result\x18\x01 \x01(\x0b\x32>.spark.connect.PipelineCommandResult.CreateDataflowGraphResultH\x00R\x19\x63reateDataflowGraphResult\x12k\n\x14\x64\x65\x66ine_output_result\x18\x02 \x01(\x0b\x32\x37.spark.connect.PipelineCommandResult.DefineOutputResultH\x00R\x12\x64\x65\x66ineOutputResult\x12\x65\n\x12\x64\x65\x66ine_flow_result\x18\x03 \x01(\x0b\x32\x35.spark.connect.PipelineCommandResult.DefineFlowResultH\x00R\x10\x64\x65\x66ineFlowResult\x1a\x62\n\x19\x43reateDataflowGraphResult\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x42\x14\n\x12_dataflow_graph_id\x1a\x85\x01\n\x12\x44\x65\x66ineOutputResult\x12W\n\x13resolved_identifier\x18\x01 \x01(\x0b\x32!.spark.connect.ResolvedIdentifierH\x00R\x12resolvedIdentifier\x88\x01\x01\x42\x16\n\x14_resolved_identifier\x1a\x83\x01\n\x10\x44\x65\x66ineFlowResult\x12W\n\x13resolved_identifier\x18\x01 \x01(\x0b\x32!.spark.connect.ResolvedIdentifierH\x00R\x12resolvedIdentifier\x88\x01\x01\x42\x16\n\x14_resolved_identifierB\r\n\x0bresult_type"I\n\x13PipelineEventResult\x12\x32\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x1c.spark.connect.PipelineEventR\x05\x65vent"t\n\rPipelineEvent\x12\x38\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\ttimestamp\x12\x1d\n\x07message\x18\x02 \x01(\tH\x00R\x07message\x88\x01\x01\x42\n\n\x08_message"\xf1\x01\n\x12SourceCodeLocation\x12 \n\tfile_name\x18\x01 \x01(\tH\x00R\x08\x66ileName\x88\x01\x01\x12$\n\x0bline_number\x18\x02 \x01(\x05H\x01R\nlineNumber\x88\x01\x01\x12,\n\x0f\x64\x65\x66inition_path\x18\x03 \x01(\tH\x02R\x0e\x64\x65\x66initionPath\x88\x01\x01\x12\x33\n\textension\x18\xe7\x07 \x03(\x0b\x32\x14.google.protobuf.AnyR\textensionB\x0c\n\n_file_nameB\x0e\n\x0c_line_numberB\x12\n\x10_definition_path"E\n$PipelineQueryFunctionExecutionSignal\x12\x1d\n\nflow_names\x18\x01 \x03(\tR\tflowNames"\x87\x02\n\x17PipelineAnalysisContext\x12/\n\x11\x64\x61taflow_graph_id\x18\x01 \x01(\tH\x00R\x0f\x64\x61taflowGraphId\x88\x01\x01\x12,\n\x0f\x64\x65\x66inition_path\x18\x02 \x01(\tH\x01R\x0e\x64\x65\x66initionPath\x88\x01\x01\x12 \n\tflow_name\x18\x03 \x01(\tH\x02R\x08\x66lowName\x88\x01\x01\x12\x33\n\textension\x18\xe7\x07 \x03(\x0b\x32\x14.google.protobuf.AnyR\textensionB\x14\n\x12_dataflow_graph_idB\x12\n\x10_definition_pathB\x0c\n\n_flow_name*i\n\nOutputType\x12\x1b\n\x17OUTPUT_TYPE_UNSPECIFIED\x10\x00\x12\x15\n\x11MATERIALIZED_VIEW\x10\x01\x12\t\n\x05TABLE\x10\x02\x12\x12\n\x0eTEMPORARY_VIEW\x10\x03\x12\x08\n\x04SINK\x10\x04\x42\x36\n\x1eorg.apache.spark.connect.protoP\x01Z\x12internal/generatedb\x06proto3' ) _globals = globals() @@ -69,62 +69,64 @@ ]._serialized_options = b"8\001" _globals["_PIPELINECOMMAND_DEFINEFLOW_SQLCONFENTRY"]._loaded_options = None _globals["_PIPELINECOMMAND_DEFINEFLOW_SQLCONFENTRY"]._serialized_options = b"8\001" - _globals["_OUTPUTTYPE"]._serialized_start = 6187 - _globals["_OUTPUTTYPE"]._serialized_end = 6292 + _globals["_OUTPUTTYPE"]._serialized_start = 6649 + _globals["_OUTPUTTYPE"]._serialized_end = 6754 _globals["_PIPELINECOMMAND"]._serialized_start = 195 - _globals["_PIPELINECOMMAND"]._serialized_end = 4656 - _globals["_PIPELINECOMMAND_CREATEDATAFLOWGRAPH"]._serialized_start = 1129 - _globals["_PIPELINECOMMAND_CREATEDATAFLOWGRAPH"]._serialized_end = 1437 - _globals["_PIPELINECOMMAND_CREATEDATAFLOWGRAPH_SQLCONFENTRY"]._serialized_start = 1338 - _globals["_PIPELINECOMMAND_CREATEDATAFLOWGRAPH_SQLCONFENTRY"]._serialized_end = 1396 - _globals["_PIPELINECOMMAND_DROPDATAFLOWGRAPH"]._serialized_start = 1439 - _globals["_PIPELINECOMMAND_DROPDATAFLOWGRAPH"]._serialized_end = 1529 - _globals["_PIPELINECOMMAND_DEFINEOUTPUT"]._serialized_start = 1532 - _globals["_PIPELINECOMMAND_DEFINEOUTPUT"]._serialized_end = 2830 - _globals["_PIPELINECOMMAND_DEFINEOUTPUT_TABLEDETAILS"]._serialized_start = 2068 - _globals["_PIPELINECOMMAND_DEFINEOUTPUT_TABLEDETAILS"]._serialized_end = 2516 + _globals["_PIPELINECOMMAND"]._serialized_end = 5118 + _globals["_PIPELINECOMMAND_CREATEDATAFLOWGRAPH"]._serialized_start = 1232 + _globals["_PIPELINECOMMAND_CREATEDATAFLOWGRAPH"]._serialized_end = 1540 + _globals["_PIPELINECOMMAND_CREATEDATAFLOWGRAPH_SQLCONFENTRY"]._serialized_start = 1441 + _globals["_PIPELINECOMMAND_CREATEDATAFLOWGRAPH_SQLCONFENTRY"]._serialized_end = 1499 + _globals["_PIPELINECOMMAND_DROPDATAFLOWGRAPH"]._serialized_start = 1542 + _globals["_PIPELINECOMMAND_DROPDATAFLOWGRAPH"]._serialized_end = 1632 + _globals["_PIPELINECOMMAND_DEFINEOUTPUT"]._serialized_start = 1635 + _globals["_PIPELINECOMMAND_DEFINEOUTPUT"]._serialized_end = 2933 + _globals["_PIPELINECOMMAND_DEFINEOUTPUT_TABLEDETAILS"]._serialized_start = 2171 + _globals["_PIPELINECOMMAND_DEFINEOUTPUT_TABLEDETAILS"]._serialized_end = 2619 _globals[ "_PIPELINECOMMAND_DEFINEOUTPUT_TABLEDETAILS_TABLEPROPERTIESENTRY" - ]._serialized_start = 2429 + ]._serialized_start = 2532 _globals[ "_PIPELINECOMMAND_DEFINEOUTPUT_TABLEDETAILS_TABLEPROPERTIESENTRY" - ]._serialized_end = 2495 - _globals["_PIPELINECOMMAND_DEFINEOUTPUT_SINKDETAILS"]._serialized_start = 2519 - _globals["_PIPELINECOMMAND_DEFINEOUTPUT_SINKDETAILS"]._serialized_end = 2728 - _globals["_PIPELINECOMMAND_DEFINEOUTPUT_SINKDETAILS_OPTIONSENTRY"]._serialized_start = 2659 - _globals["_PIPELINECOMMAND_DEFINEOUTPUT_SINKDETAILS_OPTIONSENTRY"]._serialized_end = 2717 - _globals["_PIPELINECOMMAND_DEFINEFLOW"]._serialized_start = 2833 - _globals["_PIPELINECOMMAND_DEFINEFLOW"]._serialized_end = 3728 - _globals["_PIPELINECOMMAND_DEFINEFLOW_SQLCONFENTRY"]._serialized_start = 1338 - _globals["_PIPELINECOMMAND_DEFINEFLOW_SQLCONFENTRY"]._serialized_end = 1396 - _globals["_PIPELINECOMMAND_DEFINEFLOW_WRITERELATIONFLOWDETAILS"]._serialized_start = 3452 - _globals["_PIPELINECOMMAND_DEFINEFLOW_WRITERELATIONFLOWDETAILS"]._serialized_end = 3549 - _globals["_PIPELINECOMMAND_DEFINEFLOW_RESPONSE"]._serialized_start = 3551 - _globals["_PIPELINECOMMAND_DEFINEFLOW_RESPONSE"]._serialized_end = 3609 - _globals["_PIPELINECOMMAND_STARTRUN"]._serialized_start = 3731 - _globals["_PIPELINECOMMAND_STARTRUN"]._serialized_end = 4053 - _globals["_PIPELINECOMMAND_DEFINESQLGRAPHELEMENTS"]._serialized_start = 4056 - _globals["_PIPELINECOMMAND_DEFINESQLGRAPHELEMENTS"]._serialized_end = 4255 - _globals["_PIPELINECOMMAND_GETQUERYFUNCTIONEXECUTIONSIGNALSTREAM"]._serialized_start = 4258 - _globals["_PIPELINECOMMAND_GETQUERYFUNCTIONEXECUTIONSIGNALSTREAM"]._serialized_end = 4416 - _globals["_PIPELINECOMMAND_DEFINEFLOWQUERYFUNCTIONRESULT"]._serialized_start = 4419 - _globals["_PIPELINECOMMAND_DEFINEFLOWQUERYFUNCTIONRESULT"]._serialized_end = 4640 - _globals["_PIPELINECOMMANDRESULT"]._serialized_start = 4659 - _globals["_PIPELINECOMMANDRESULT"]._serialized_end = 5411 - _globals["_PIPELINECOMMANDRESULT_CREATEDATAFLOWGRAPHRESULT"]._serialized_start = 5028 - _globals["_PIPELINECOMMANDRESULT_CREATEDATAFLOWGRAPHRESULT"]._serialized_end = 5126 - _globals["_PIPELINECOMMANDRESULT_DEFINEOUTPUTRESULT"]._serialized_start = 5129 - _globals["_PIPELINECOMMANDRESULT_DEFINEOUTPUTRESULT"]._serialized_end = 5262 - _globals["_PIPELINECOMMANDRESULT_DEFINEFLOWRESULT"]._serialized_start = 5265 - _globals["_PIPELINECOMMANDRESULT_DEFINEFLOWRESULT"]._serialized_end = 5396 - _globals["_PIPELINEEVENTRESULT"]._serialized_start = 5413 - _globals["_PIPELINEEVENTRESULT"]._serialized_end = 5486 - _globals["_PIPELINEEVENT"]._serialized_start = 5488 - _globals["_PIPELINEEVENT"]._serialized_end = 5604 - _globals["_SOURCECODELOCATION"]._serialized_start = 5607 - _globals["_SOURCECODELOCATION"]._serialized_end = 5848 - _globals["_PIPELINEQUERYFUNCTIONEXECUTIONSIGNAL"]._serialized_start = 5850 - _globals["_PIPELINEQUERYFUNCTIONEXECUTIONSIGNAL"]._serialized_end = 5919 - _globals["_PIPELINEANALYSISCONTEXT"]._serialized_start = 5922 - _globals["_PIPELINEANALYSISCONTEXT"]._serialized_end = 6185 + ]._serialized_end = 2598 + _globals["_PIPELINECOMMAND_DEFINEOUTPUT_SINKDETAILS"]._serialized_start = 2622 + _globals["_PIPELINECOMMAND_DEFINEOUTPUT_SINKDETAILS"]._serialized_end = 2831 + _globals["_PIPELINECOMMAND_DEFINEOUTPUT_SINKDETAILS_OPTIONSENTRY"]._serialized_start = 2762 + _globals["_PIPELINECOMMAND_DEFINEOUTPUT_SINKDETAILS_OPTIONSENTRY"]._serialized_end = 2820 + _globals["_PIPELINECOMMAND_DEFINEFLOW"]._serialized_start = 2936 + _globals["_PIPELINECOMMAND_DEFINEFLOW"]._serialized_end = 3831 + _globals["_PIPELINECOMMAND_DEFINEFLOW_SQLCONFENTRY"]._serialized_start = 1441 + _globals["_PIPELINECOMMAND_DEFINEFLOW_SQLCONFENTRY"]._serialized_end = 1499 + _globals["_PIPELINECOMMAND_DEFINEFLOW_WRITERELATIONFLOWDETAILS"]._serialized_start = 3555 + _globals["_PIPELINECOMMAND_DEFINEFLOW_WRITERELATIONFLOWDETAILS"]._serialized_end = 3652 + _globals["_PIPELINECOMMAND_DEFINEFLOW_RESPONSE"]._serialized_start = 3654 + _globals["_PIPELINECOMMAND_DEFINEFLOW_RESPONSE"]._serialized_end = 3712 + _globals["_PIPELINECOMMAND_EXECUTEOUTPUTFLOWS"]._serialized_start = 3834 + _globals["_PIPELINECOMMAND_EXECUTEOUTPUTFLOWS"]._serialized_end = 4190 + _globals["_PIPELINECOMMAND_STARTRUN"]._serialized_start = 4193 + _globals["_PIPELINECOMMAND_STARTRUN"]._serialized_end = 4515 + _globals["_PIPELINECOMMAND_DEFINESQLGRAPHELEMENTS"]._serialized_start = 4518 + _globals["_PIPELINECOMMAND_DEFINESQLGRAPHELEMENTS"]._serialized_end = 4717 + _globals["_PIPELINECOMMAND_GETQUERYFUNCTIONEXECUTIONSIGNALSTREAM"]._serialized_start = 4720 + _globals["_PIPELINECOMMAND_GETQUERYFUNCTIONEXECUTIONSIGNALSTREAM"]._serialized_end = 4878 + _globals["_PIPELINECOMMAND_DEFINEFLOWQUERYFUNCTIONRESULT"]._serialized_start = 4881 + _globals["_PIPELINECOMMAND_DEFINEFLOWQUERYFUNCTIONRESULT"]._serialized_end = 5102 + _globals["_PIPELINECOMMANDRESULT"]._serialized_start = 5121 + _globals["_PIPELINECOMMANDRESULT"]._serialized_end = 5873 + _globals["_PIPELINECOMMANDRESULT_CREATEDATAFLOWGRAPHRESULT"]._serialized_start = 5490 + _globals["_PIPELINECOMMANDRESULT_CREATEDATAFLOWGRAPHRESULT"]._serialized_end = 5588 + _globals["_PIPELINECOMMANDRESULT_DEFINEOUTPUTRESULT"]._serialized_start = 5591 + _globals["_PIPELINECOMMANDRESULT_DEFINEOUTPUTRESULT"]._serialized_end = 5724 + _globals["_PIPELINECOMMANDRESULT_DEFINEFLOWRESULT"]._serialized_start = 5727 + _globals["_PIPELINECOMMANDRESULT_DEFINEFLOWRESULT"]._serialized_end = 5858 + _globals["_PIPELINEEVENTRESULT"]._serialized_start = 5875 + _globals["_PIPELINEEVENTRESULT"]._serialized_end = 5948 + _globals["_PIPELINEEVENT"]._serialized_start = 5950 + _globals["_PIPELINEEVENT"]._serialized_end = 6066 + _globals["_SOURCECODELOCATION"]._serialized_start = 6069 + _globals["_SOURCECODELOCATION"]._serialized_end = 6310 + _globals["_PIPELINEQUERYFUNCTIONEXECUTIONSIGNAL"]._serialized_start = 6312 + _globals["_PIPELINEQUERYFUNCTIONEXECUTIONSIGNAL"]._serialized_end = 6381 + _globals["_PIPELINEANALYSISCONTEXT"]._serialized_start = 6384 + _globals["_PIPELINEANALYSISCONTEXT"]._serialized_end = 6647 # @@protoc_insertion_point(module_scope) diff --git a/python/pyspark/sql/connect/proto/pipelines_pb2.pyi b/python/pyspark/sql/connect/proto/pipelines_pb2.pyi index 39a1e29ae7dde..391746c049937 100644 --- a/python/pyspark/sql/connect/proto/pipelines_pb2.pyi +++ b/python/pyspark/sql/connect/proto/pipelines_pb2.pyi @@ -740,6 +740,98 @@ class PipelineCommand(google.protobuf.message.Message): self, oneof_group: typing_extensions.Literal["details", b"details"] ) -> typing_extensions.Literal["relation_flow_details", "extension"] | None: ... + class ExecuteOutputFlows(google.protobuf.message.Message): + """Request to execute all flows for a single output (dataset or sink) remotely.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + DEFINE_OUTPUT_FIELD_NUMBER: builtins.int + DEFINE_FLOWS_FIELD_NUMBER: builtins.int + FULL_REFRESH_FIELD_NUMBER: builtins.int + STORAGE_FIELD_NUMBER: builtins.int + EXTENSION_FIELD_NUMBER: builtins.int + @property + def define_output(self) -> global___PipelineCommand.DefineOutput: + """The output (table or materialized view or sink) definition.""" + @property + def define_flows( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + global___PipelineCommand.DefineFlow + ]: + """The flows to execute for this table.""" + full_refresh: builtins.bool + """Whether to perform a full refresh instead of an incremental update.""" + storage: builtins.str + """Storage location for pipeline checkpoints and metadata.""" + @property + def extension( + self, + ) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[ + google.protobuf.any_pb2.Any + ]: + """Reserved field for protocol extensions.""" + def __init__( + self, + *, + define_output: global___PipelineCommand.DefineOutput | None = ..., + define_flows: collections.abc.Iterable[global___PipelineCommand.DefineFlow] + | None = ..., + full_refresh: builtins.bool | None = ..., + storage: builtins.str | None = ..., + extension: collections.abc.Iterable[google.protobuf.any_pb2.Any] | None = ..., + ) -> None: ... + def HasField( + self, + field_name: typing_extensions.Literal[ + "_define_output", + b"_define_output", + "_full_refresh", + b"_full_refresh", + "_storage", + b"_storage", + "define_output", + b"define_output", + "full_refresh", + b"full_refresh", + "storage", + b"storage", + ], + ) -> builtins.bool: ... + def ClearField( + self, + field_name: typing_extensions.Literal[ + "_define_output", + b"_define_output", + "_full_refresh", + b"_full_refresh", + "_storage", + b"_storage", + "define_flows", + b"define_flows", + "define_output", + b"define_output", + "extension", + b"extension", + "full_refresh", + b"full_refresh", + "storage", + b"storage", + ], + ) -> None: ... + @typing.overload + def WhichOneof( + self, oneof_group: typing_extensions.Literal["_define_output", b"_define_output"] + ) -> typing_extensions.Literal["define_output"] | None: ... + @typing.overload + def WhichOneof( + self, oneof_group: typing_extensions.Literal["_full_refresh", b"_full_refresh"] + ) -> typing_extensions.Literal["full_refresh"] | None: ... + @typing.overload + def WhichOneof( + self, oneof_group: typing_extensions.Literal["_storage", b"_storage"] + ) -> typing_extensions.Literal["storage"] | None: ... + class StartRun(google.protobuf.message.Message): """Resolves all datasets and flows and start a pipeline update. Should be called after all graph elements are registered. @@ -1051,6 +1143,7 @@ class PipelineCommand(google.protobuf.message.Message): DEFINE_SQL_GRAPH_ELEMENTS_FIELD_NUMBER: builtins.int GET_QUERY_FUNCTION_EXECUTION_SIGNAL_STREAM_FIELD_NUMBER: builtins.int DEFINE_FLOW_QUERY_FUNCTION_RESULT_FIELD_NUMBER: builtins.int + EXECUTE_OUTPUT_FLOWS_FIELD_NUMBER: builtins.int EXTENSION_FIELD_NUMBER: builtins.int @property def create_dataflow_graph(self) -> global___PipelineCommand.CreateDataflowGraph: ... @@ -1073,6 +1166,8 @@ class PipelineCommand(google.protobuf.message.Message): self, ) -> global___PipelineCommand.DefineFlowQueryFunctionResult: ... @property + def execute_output_flows(self) -> global___PipelineCommand.ExecuteOutputFlows: ... + @property def extension(self) -> google.protobuf.any_pb2.Any: """Reserved field for protocol extensions. Used to support forward-compatibility by carrying additional command types @@ -1092,6 +1187,7 @@ class PipelineCommand(google.protobuf.message.Message): | None = ..., define_flow_query_function_result: global___PipelineCommand.DefineFlowQueryFunctionResult | None = ..., + execute_output_flows: global___PipelineCommand.ExecuteOutputFlows | None = ..., extension: google.protobuf.any_pb2.Any | None = ..., ) -> None: ... def HasField( @@ -1111,6 +1207,8 @@ class PipelineCommand(google.protobuf.message.Message): b"define_sql_graph_elements", "drop_dataflow_graph", b"drop_dataflow_graph", + "execute_output_flows", + b"execute_output_flows", "extension", b"extension", "get_query_function_execution_signal_stream", @@ -1136,6 +1234,8 @@ class PipelineCommand(google.protobuf.message.Message): b"define_sql_graph_elements", "drop_dataflow_graph", b"drop_dataflow_graph", + "execute_output_flows", + b"execute_output_flows", "extension", b"extension", "get_query_function_execution_signal_stream", @@ -1156,6 +1256,7 @@ class PipelineCommand(google.protobuf.message.Message): "define_sql_graph_elements", "get_query_function_execution_signal_stream", "define_flow_query_function_result", + "execute_output_flows", "extension", ] | None diff --git a/sql/connect/common/src/main/protobuf/spark/connect/pipelines.proto b/sql/connect/common/src/main/protobuf/spark/connect/pipelines.proto index 0874c2d10ec5c..a46c7a75bc9ba 100644 --- a/sql/connect/common/src/main/protobuf/spark/connect/pipelines.proto +++ b/sql/connect/common/src/main/protobuf/spark/connect/pipelines.proto @@ -40,6 +40,8 @@ message PipelineCommand { DefineSqlGraphElements define_sql_graph_elements = 6; GetQueryFunctionExecutionSignalStream get_query_function_execution_signal_stream = 7; DefineFlowQueryFunctionResult define_flow_query_function_result = 8; + ExecuteOutputFlows execute_output_flows = 9; + // Reserved field for protocol extensions. // Used to support forward-compatibility by carrying additional command types // that are not yet defined in this version of the proto. During planning, the @@ -165,6 +167,25 @@ message PipelineCommand { } } + // Request to execute all flows for a single output (dataset or sink) remotely. + message ExecuteOutputFlows { + + // The output (table or materialized view or sink) definition. + optional DefineOutput define_output = 1; + + // The flows to execute for this table. + repeated DefineFlow define_flows = 2; + + // Whether to perform a full refresh instead of an incremental update. + optional bool full_refresh = 3; + + // Storage location for pipeline checkpoints and metadata. + optional string storage = 4; + + // Reserved field for protocol extensions. + repeated google.protobuf.Any extension = 999; + } + // Resolves all datasets and flows and start a pipeline update. Should be called after all // graph elements are registered. message StartRun { From 7529622911aa29aca89aaf55ccf4880b00fa2560 Mon Sep 17 00:00:00 2001 From: Eren Avsarogullari Date: Tue, 24 Feb 2026 23:53:45 +0800 Subject: [PATCH 011/130] [SPARK-55052][SQL] Add AQEShuffleRead properties to Physical Plan Tree ### What changes were proposed in this pull request? `AQEShuffleRead` can have `local` / `coalesced` / `skewed` / `coalesced and skewed` properties when reading shuffle files. When Physical Plan Tree is complex, it is hard to track this info by correlating with AQEShuffleRead details such as which AQEShuffleRead has local read or skewed partition info etc. For example, following skewed SortMergeJoin case, this helps to understand which SMJ leg has AQEShuffleRead with skew. This addition aims to access this kind of use-cases at physical plan tree level. Plan Tree details section per AQEShuffleRead node also shows these properties but when query plan tree is too complex (e.g: composed by 1000+ physical nodes), it is hard to correlate this information with AQEShuffleRead details. **Current Physical Plan Tree:** ``` == Physical Plan == AdaptiveSparkPlan (24) +- == Final Plan == ResultQueryStage (17), Statistics(sizeInBytes=8.0 EiB) +- * Project (16) +- * SortMergeJoin(skew=true) Inner (15) :- * Sort (7) : +- AQEShuffleRead (6) : +- ShuffleQueryStage (5), Statistics(sizeInBytes=15.6 KiB, rowCount=1.00E+3) : +- Exchange (4) : +- * Project (3) : +- * Filter (2) : +- * Range (1) +- * Sort (14) +- AQEShuffleRead (13) +- ShuffleQueryStage (12), Statistics(sizeInBytes=3.1 KiB, rowCount=200) +- Exchange (11) +- * Project (10) +- * Filter (9) +- * Range (8) ``` **New Physical Plan Tree:** ``` == Physical Plan == AdaptiveSparkPlan (24) +- == Final Plan == ResultQueryStage (17), Statistics(sizeInBytes=8.0 EiB) +- * Project (16) +- * SortMergeJoin(skew=true) Inner (15) :- * Sort (7) : +- AQEShuffleRead (6), coalesced : +- ShuffleQueryStage (5), Statistics(sizeInBytes=15.6 KiB, rowCount=1.00E+3) : +- Exchange (4) : +- * Project (3) : +- * Filter (2) : +- * Range (1) +- * Sort (14) +- AQEShuffleRead (13), coalesced and skewed +- ShuffleQueryStage (12), Statistics(sizeInBytes=3.1 KiB, rowCount=200) +- Exchange (11) +- * Project (10) +- * Filter (9) +- * Range (8) ``` ### Why are the changes needed? When physical plan tree is complex (e.g: composed by 1000+ physical nodes), it is hard to correlate this information with `AQEShuffleRead` details. ### Does this PR introduce _any_ user-facing change? Yes, when the user investigates the physical plan, new AQEShuffleRead properties will be seen at Physical Plan Tree. ### How was this patch tested? Added a new UT ### Was this patch authored or co-authored using generative AI tooling? No Closes #53817 from erenavsarogullari/SPARK-55052. Authored-by: Eren Avsarogullari Signed-off-by: Wenchen Fan --- .../adaptive/AQEShuffleReadExec.scala | 10 ++++ .../org/apache/spark/sql/ExplainSuite.scala | 56 ++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/adaptive/AQEShuffleReadExec.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/adaptive/AQEShuffleReadExec.scala index 2a600b31cc297..eba0346a94bd0 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/adaptive/AQEShuffleReadExec.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/adaptive/AQEShuffleReadExec.scala @@ -278,4 +278,14 @@ case class AQEShuffleReadExec private( override protected def withNewChildInternal(newChild: SparkPlan): AQEShuffleReadExec = copy(child = newChild) + + override def simpleStringWithNodeId(): String = { + val args = stringArgs.mkString(", ") + if (args.nonEmpty) { + super.simpleStringWithNodeId() + ", " + args + } else { + super.simpleStringWithNodeId() + } + } + } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/ExplainSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/ExplainSuite.scala index b27122a8de2bc..e2a01775b89d9 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/ExplainSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/ExplainSuite.scala @@ -20,7 +20,7 @@ package org.apache.spark.sql import org.apache.spark.sql.catalyst.plans.Inner import org.apache.spark.sql.catalyst.plans.physical.RoundRobinPartitioning import org.apache.spark.sql.execution._ -import org.apache.spark.sql.execution.adaptive.{DisableAdaptiveExecutionSuite, EnableAdaptiveExecutionSuite} +import org.apache.spark.sql.execution.adaptive.{AQEPropagateEmptyRelation, DisableAdaptiveExecutionSuite, EnableAdaptiveExecutionSuite} import org.apache.spark.sql.execution.datasources.SaveIntoDataSourceCommand import org.apache.spark.sql.execution.exchange.{ReusedExchangeExec, ShuffleExchangeExec} import org.apache.spark.sql.execution.joins.SortMergeJoinExec @@ -941,6 +941,60 @@ class ExplainSuiteAE extends ExplainSuiteHelper with EnableAdaptiveExecutionSuit results = results.replaceAll("#\\d+", "#x").replaceAll("plan_id=\\d+", "plan_id=x") assert(results == expectedTree) } + + test("SPARK-55052: Verify exposed AQEShuffleRead properties (coalesced and coalesced-skewed) " + + "in Physical Plan Tree") { + withSQLConf( + SQLConf.ADAPTIVE_EXECUTION_ENABLED.key -> "true", + SQLConf.AUTO_BROADCASTJOIN_THRESHOLD.key -> "-1", + SQLConf.SKEW_JOIN_SKEWED_PARTITION_THRESHOLD.key -> "100", + SQLConf.ADVISORY_PARTITION_SIZE_IN_BYTES.key -> "100", + SQLConf.SHUFFLE_PARTITIONS.key -> "10") { + withTempView("view1", "skewDataView2") { + spark + .range(0, 1000, 1, 10) + .selectExpr("id % 10 as key1") + .createOrReplaceTempView("view1") + spark + .range(0, 200, 1, 10) + .selectExpr("id % 1 as key2") + .createOrReplaceTempView("skewDataView2") + + val df = spark.sql("SELECT key1 FROM view1 JOIN skewDataView2 ON key1 = key2") + df.collect() + + // Verify expected FinalPlan substring including AQEShuffleRead properties + checkKeywordsExistsInExplain( + df = df, + mode = ExplainMode.fromString("FORMATTED"), + keywords = "AQEShuffleRead (6), coalesced", "AQEShuffleRead (13), coalesced and skewed") + } + } + } + + test("SPARK-55052: Verify exposed AQEShuffleRead properties (local) in Physical Plan Tree") { + withSQLConf( + SQLConf.ADAPTIVE_EXECUTION_ENABLED.key -> "true", + SQLConf.COALESCE_PARTITIONS_ENABLED.key -> "true", + SQLConf.ADAPTIVE_OPTIMIZER_EXCLUDED_RULES.key -> AQEPropagateEmptyRelation.ruleName, + SQLConf.AUTO_BROADCASTJOIN_THRESHOLD.key -> "1" + ) { + val df1 = spark.range(10).withColumn("a", $"id") + val df2 = spark.range(10).withColumn("b", $"id") + + val joinedDF = df1.where($"a" > 10) + .join(df2.where($"b" > 10), Seq("id"), "left_outer") + checkAnswer(joinedDF, Seq()) + joinedDF.collect() + + // Verify expected FinalPlan substring including AQEShuffleRead properties + checkKeywordsExistsInExplain( + df = joinedDF, + mode = ExplainMode.fromString("FORMATTED"), + keywords = "AQEShuffleRead (6), local", "AQEShuffleRead (9), local") + } + } + } case class ExplainSingleData(id: Int) From 52a9f01cb05ec06bdf334fe469b72b39f5c10516 Mon Sep 17 00:00:00 2001 From: Szehon Ho Date: Tue, 24 Feb 2026 23:59:07 +0800 Subject: [PATCH 012/130] [SPARK-55622][SQL][TESTS] Add test for DSV2 Tables with multi-part names on SessionCatalog ### What changes were proposed in this pull request? Add a unit test for Iceberg's case of supporting multi part identifiers in SessionCatalog (for metadata tables). Add a fake metadata table to InMemoryDataSource. ### Why are the changes needed? It can increase Spark coverage to catch issue like: https://github.com/apache/spark/pull/54247 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Ran the added test ### Was this patch authored or co-authored using generative AI tooling? Yes, cursor claude 4.5 opus Closes #54411 from szehon-ho/add_test. Authored-by: Szehon Ho Signed-off-by: Cheng Pan --- .../sql/connector/catalog/InMemoryTable.scala | 72 ++++++++++++++++++- ...SourceV2DataFrameSessionCatalogSuite.scala | 24 ++++++- .../DataSourceV2SQLSessionCatalogSuite.scala | 32 +++++++++ 3 files changed, 125 insertions(+), 3 deletions(-) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryTable.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryTable.scala index 3bea136b34d46..d5738475031dc 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryTable.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryTable.scala @@ -20,12 +20,14 @@ package org.apache.spark.sql.connector.catalog import java.util import java.util.{Objects, UUID} +import org.apache.spark.sql.catalyst.InternalRow import org.apache.spark.sql.connector.catalog.constraints.Constraint import org.apache.spark.sql.connector.distributions.{Distribution, Distributions} import org.apache.spark.sql.connector.expressions.{SortOrder, Transform} +import org.apache.spark.sql.connector.read._ import org.apache.spark.sql.connector.write.{LogicalWriteInfo, SupportsOverwrite, WriteBuilder, WriterCommitMessage} import org.apache.spark.sql.sources._ -import org.apache.spark.sql.types.StructType +import org.apache.spark.sql.types.{LongType, StructField, StructType} import org.apache.spark.sql.util.CaseInsensitiveStringMap import org.apache.spark.util.ArrayImplicits._ @@ -261,3 +263,71 @@ object InMemoryTable { } } } + +/** + * A metadata table that returns snapshot (commit) information for a parent table. + * Simulates data source tables with multi-part identifiers, ex Iceberg's db.table.snapshots. + */ +class InMemorySnapshotsTable(parentTable: InMemoryTable) extends Table with SupportsRead { + override def name(): String = parentTable.name + ".snapshots" + + override def schema(): StructType = StructType(Seq( + StructField("committed_at", LongType, nullable = false), + StructField("snapshot_id", LongType, nullable = false) + )) + + override def capabilities(): util.Set[TableCapability] = { + util.EnumSet.of(TableCapability.BATCH_READ) + } + + override def newScanBuilder(options: CaseInsensitiveStringMap): ScanBuilder = { + new InMemorySnapshotsScanBuilder(parentTable) + } +} + +class InMemorySnapshotsScanBuilder(parentTable: InMemoryTable) extends ScanBuilder { + override def build(): Scan = new InMemorySnapshotsScan(parentTable) +} + +class InMemorySnapshotsScan(parentTable: InMemoryTable) extends Scan with Batch { + override def readSchema(): StructType = StructType(Seq( + StructField("committed_at", LongType, nullable = false), + StructField("snapshot_id", LongType, nullable = false) + )) + + override def toBatch: Batch = this + + override def planInputPartitions(): Array[InputPartition] = { + Array(InMemorySnapshotsPartition(parentTable.commits.toSeq.map(c => (c.id, c.id)))) + } + + override def createReaderFactory(): PartitionReaderFactory = { + new InMemorySnapshotsReaderFactory() + } +} + +case class InMemorySnapshotsPartition(snapshots: Seq[(Long, Long)]) extends InputPartition + +class InMemorySnapshotsReaderFactory extends PartitionReaderFactory { + override def createReader(partition: InputPartition): PartitionReader[InternalRow] = { + new InMemorySnapshotsReader(partition.asInstanceOf[InMemorySnapshotsPartition]) + } +} + +class InMemorySnapshotsReader(partition: InMemorySnapshotsPartition) + extends PartitionReader[InternalRow] { + private var index = -1 + private val snapshots = partition.snapshots + + override def next(): Boolean = { + index += 1 + index < snapshots.size + } + + override def get(): InternalRow = { + val (committedAt, snapshotId) = snapshots(index) + InternalRow(committedAt, snapshotId) + } + + override def close(): Unit = {} +} diff --git a/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2DataFrameSessionCatalogSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2DataFrameSessionCatalogSuite.scala index bc6ceeb24593b..c3a24765fc2b0 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2DataFrameSessionCatalogSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2DataFrameSessionCatalogSuite.scala @@ -17,9 +17,11 @@ package org.apache.spark.sql.connector +import java.util.Locale + import org.scalatest.BeforeAndAfter -import org.apache.spark.sql.{DataFrame, QueryTest, SaveMode} +import org.apache.spark.sql.{AnalysisException, DataFrame, QueryTest, SaveMode} import org.apache.spark.sql.catalyst.TableIdentifier import org.apache.spark.sql.catalyst.analysis.TableAlreadyExistsException import org.apache.spark.sql.connector.catalog._ @@ -111,7 +113,25 @@ class InMemoryTableSessionCatalog extends TestV2SessionCatalogBase[InMemoryTable val identToUse = Option(InMemoryTableSessionCatalog.customIdentifierResolution) .map(_(ident)) .getOrElse(ident) - super.loadTable(identToUse) + + // For single-part namespaces, follow Iceberg's pattern: first try to load the table + // normally, fall back to metadata table resolution only on NoSuchTableException + try { + super.loadTable(identToUse) + } catch { + case _: AnalysisException if identToUse.name().toLowerCase(Locale.ROOT) == "snapshots" => + loadSnapshotTable(identToUse) + } + } + + private def loadSnapshotTable(ident: Identifier): InMemorySnapshotsTable = { + val parentTableName = ident.namespace().last + val parentNamespace = ident.namespace().dropRight(1) + val parentIdent = Identifier.of( + if (parentNamespace.isEmpty) Array("default") else parentNamespace, + parentTableName) + val parentTable = super.loadTable(parentIdent).asInstanceOf[InMemoryTable] + new InMemorySnapshotsTable(parentTable) } override def alterTable(ident: Identifier, changes: TableChange*): Table = { diff --git a/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2SQLSessionCatalogSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2SQLSessionCatalogSuite.scala index dcc49b252fdbd..9c3b429e829bb 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2SQLSessionCatalogSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2SQLSessionCatalogSuite.scala @@ -86,4 +86,36 @@ class DataSourceV2SQLSessionCatalogSuite sql("SELECT char_length('Hello') as v1, ns.strlen('Spark') as v2"), Row(5, 5)) } + + test("SPARK-55024: data source metadata tables with multi-part identifiers") { + // This test querying data source tables with multi part identifiers, + // with the example of Iceberg's metadata table, eg db.table.snapshots + val t1 = "metadata_test_tbl" + + def verifySnapshots(snapshots: DataFrame, expectedCount: Int, queryDesc: String): Unit = { + assert(snapshots.count() == expectedCount, + s"$queryDesc: expected $expectedCount snapshots") + assert(snapshots.schema.fieldNames.toSeq == Seq("committed_at", "snapshot_id"), + s"$queryDesc: expected schema [committed_at, snapshot_id], " + + s"got: ${snapshots.schema.fieldNames.toSeq}") + val snapshotIds = snapshots.select("snapshot_id").collect().map(_.getLong(0)) + assert(snapshotIds.forall(_ > 0), + s"$queryDesc: all snapshot IDs should be positive, got: ${snapshotIds.toSeq}") + } + + withTable(t1) { + sql(s"CREATE TABLE $t1 (id bigint, data string) USING $v2Format") + sql(s"INSERT INTO $t1 VALUES (1, 'first')") + sql(s"INSERT INTO $t1 VALUES (2, 'second')") + sql(s"INSERT INTO $t1 VALUES (3, 'third')") + + Seq( + s"$t1.snapshots", + s"default.$t1.snapshots", + s"spark_catalog.default.$t1.snapshots" + ).foreach { snapshotTable => + verifySnapshots(sql(s"SELECT * FROM $snapshotTable"), 3, snapshotTable) + } + } + } } From b27eabf3061c7505b7b63c9675a6d88ddd89e5b1 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Tue, 24 Feb 2026 08:57:05 -0800 Subject: [PATCH 013/130] [SPARK-55659][CORE] Improve `EventLogFileWriter` to log `stop` operation ### What changes were proposed in this pull request? This PR aims to improve `EventLogFileWriter` to log `stop` operation. ### Why are the changes needed? Apache Spark has been logging the start of event log processing. We had better log the end of event log processing as a pair. **BEFORE** ``` $ bin/run-example -c spark.eventLog.enabled=true -c spark.eventLog.dir=/tmp SparkPi 2>&1 | grep RollingEventLogFilesWriter 26/02/24 08:24:27 INFO RollingEventLogFilesWriter: Logging events to file:/private/tmp/eventlog_v2_local-1771950267185/events_1_local-1771950267185.zstd ``` **AFTER** ``` $ bin/run-example -c spark.eventLog.enabled=true -c spark.eventLog.dir=/tmp SparkPi 2>&1 | grep RollingEventLogFilesWriter 26/02/24 08:24:41 INFO RollingEventLogFilesWriter: Logging events to file:/private/tmp/eventlog_v2_local-1771950279197/events_1_local-1771950279197.zstd 26/02/24 08:24:42 INFO RollingEventLogFilesWriter: Stopping event writer for file:/private/tmp/eventlog_v2_local-1771950279197 ``` ### Does this PR introduce _any_ user-facing change? No behavior change because this is a log. ### How was this patch tested? Manual test. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54452 from dongjoon-hyun/SPARK-55659. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- .../org/apache/spark/deploy/history/EventLogFileWriters.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/scala/org/apache/spark/deploy/history/EventLogFileWriters.scala b/core/src/main/scala/org/apache/spark/deploy/history/EventLogFileWriters.scala index 7c022c283db41..601515e57dc82 100644 --- a/core/src/main/scala/org/apache/spark/deploy/history/EventLogFileWriters.scala +++ b/core/src/main/scala/org/apache/spark/deploy/history/EventLogFileWriters.scala @@ -250,6 +250,7 @@ class SingleEventLogFileWriter( * ".inprogress" suffix. */ override def stop(): Unit = { + logInfo(log"Stopping event writer for ${MDC(PATH, logPath)}") closeWriter() renameFile(new Path(inProgressPath), new Path(logPath), shouldOverwrite) } @@ -367,6 +368,7 @@ class RollingEventLogFilesWriter( } override def stop(): Unit = { + logInfo(log"Stopping event writer for ${MDC(PATH, logPath)}") closeWriter() val appStatusPathIncomplete = getAppStatusFilePath(logDirForAppPath, appId, appAttemptId, inProgress = true) From 7fca140e3b3a7509ff68ed8e2d54db5190af3621 Mon Sep 17 00:00:00 2001 From: Takuya Ueshin Date: Tue, 24 Feb 2026 12:13:40 -0800 Subject: [PATCH 014/130] [SPARK-55648][PS] Handle an unexpected keyword argument error `groupby(axis)` with pandas 3 ### What changes were proposed in this pull request? Handles an unexpected keyword argument error `groupby(axis)` with pandas 3. ### Why are the changes needed? The `axis` argument was removed from `groupby` in pandas 3. ### Does this PR introduce _any_ user-facing change? Yes, it will behave more like pandas 3. ### How was this patch tested? Updated the related tests. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54436 from ueshin/issues/SPARK-55648/axis. Lead-authored-by: Takuya Ueshin Co-authored-by: Takuya UESHIN Signed-off-by: Takuya Ueshin --- python/pyspark/pandas/frame.py | 2 +- python/pyspark/pandas/generic.py | 15 +++-- python/pyspark/pandas/series.py | 2 +- .../pandas/tests/groupby/test_groupby.py | 60 +++++++++++-------- 4 files changed, 47 insertions(+), 32 deletions(-) diff --git a/python/pyspark/pandas/frame.py b/python/pyspark/pandas/frame.py index 5609f76cd7196..aeb47709766ca 100644 --- a/python/pyspark/pandas/frame.py +++ b/python/pyspark/pandas/frame.py @@ -13658,7 +13658,7 @@ def from_dict( def groupby( self, by: Union[Name, "Series", List[Union[Name, "Series"]]], - axis: Axis = 0, + axis: Union[Axis, _NoValueType] = _NoValue, as_index: bool = True, dropna: bool = True, ) -> "DataFrameGroupBy": diff --git a/python/pyspark/pandas/generic.py b/python/pyspark/pandas/generic.py index f735804444499..cfd566e205733 100644 --- a/python/pyspark/pandas/generic.py +++ b/python/pyspark/pandas/generic.py @@ -2397,7 +2397,7 @@ def abs(psser: "Series") -> Union["Series", Column]: def groupby( self: FrameLike, by: Union[Name, "Series", List[Union[Name, "Series"]]], - axis: Axis = 0, + axis: Union[Axis, _NoValueType] = _NoValue, as_index: bool = True, dropna: bool = True, ) -> "GroupBy[FrameLike]": @@ -2518,9 +2518,16 @@ def groupby( raise ValueError("Grouper for '{}' not 1-dimensional".format(type(by).__name__)) if not len(new_by): raise ValueError("No group keys passed!") - axis = validate_axis(axis) - if axis != 0: - raise NotImplementedError('axis should be either 0 or "index" currently.') + + if LooseVersion(pd.__version__) < "3.0.0": + if axis is _NoValue: + axis = 0 + axis = validate_axis(axis) # type: ignore[arg-type] + if axis != 0: + raise NotImplementedError('axis should be either 0 or "index" currently.') + else: + if axis is not _NoValue: + raise TypeError("The 'axis' keyword is not supported in pandas 3.0.0 and later.") return self._build_groupby(by=new_by, as_index=as_index, dropna=dropna) diff --git a/python/pyspark/pandas/series.py b/python/pyspark/pandas/series.py index 72d49574423b0..3f8a2e57792da 100644 --- a/python/pyspark/pandas/series.py +++ b/python/pyspark/pandas/series.py @@ -7195,7 +7195,7 @@ def _reduce_for_stat_function( def groupby( self, by: Union[Name, "Series", List[Union[Name, "Series"]]], - axis: Axis = 0, + axis: Union[Axis, _NoValueType] = _NoValue, as_index: bool = True, dropna: bool = True, ) -> "SeriesGroupBy": diff --git a/python/pyspark/pandas/tests/groupby/test_groupby.py b/python/pyspark/pandas/tests/groupby/test_groupby.py index 92bb84a5c341d..91ea9168c7104 100644 --- a/python/pyspark/pandas/tests/groupby/test_groupby.py +++ b/python/pyspark/pandas/tests/groupby/test_groupby.py @@ -20,6 +20,7 @@ import pandas as pd from pyspark import pandas as ps +from pyspark.loose_version import LooseVersion from pyspark.pandas.groupby import is_multi_agg_with_relabel from pyspark.testing.pandasutils import PandasOnSparkTestCase, TestUtils @@ -92,28 +93,29 @@ def sort(df): psdf.a.groupby(psdf.b).sum().sort_index(), pdf.a.groupby(pdf.b).sum().sort_index() ) - for axis in [0, "index"]: - self.assert_eq( - psdf.groupby("a", axis=axis).a.sum().sort_index(), - pdf.groupby("a", axis=axis).a.sum().sort_index(), - ) - self.assert_eq( - psdf.groupby("a", axis=axis)["a"].sum().sort_index(), - pdf.groupby("a", axis=axis)["a"].sum().sort_index(), - ) - self.assert_eq( - psdf.groupby("a", axis=axis)[["a"]].sum().sort_index(), - pdf.groupby("a", axis=axis)[["a"]].sum().sort_index(), - ) - self.assert_eq( - psdf.groupby("a", axis=axis)[["a", "c"]].sum().sort_index(), - pdf.groupby("a", axis=axis)[["a", "c"]].sum().sort_index(), - ) - - self.assert_eq( - psdf.a.groupby(psdf.b, axis=axis).sum().sort_index(), - pdf.a.groupby(pdf.b, axis=axis).sum().sort_index(), - ) + if LooseVersion(pd.__version__) < "3.0.0": + for axis in [0, "index"]: + self.assert_eq( + psdf.groupby("a", axis=axis).a.sum().sort_index(), + pdf.groupby("a", axis=axis).a.sum().sort_index(), + ) + self.assert_eq( + psdf.groupby("a", axis=axis)["a"].sum().sort_index(), + pdf.groupby("a", axis=axis)["a"].sum().sort_index(), + ) + self.assert_eq( + psdf.groupby("a", axis=axis)[["a"]].sum().sort_index(), + pdf.groupby("a", axis=axis)[["a"]].sum().sort_index(), + ) + self.assert_eq( + psdf.groupby("a", axis=axis)[["a", "c"]].sum().sort_index(), + pdf.groupby("a", axis=axis)[["a", "c"]].sum().sort_index(), + ) + + self.assert_eq( + psdf.a.groupby(psdf.b, axis=axis).sum().sort_index(), + pdf.a.groupby(pdf.b, axis=axis).sum().sort_index(), + ) self.assertRaises(ValueError, lambda: psdf.groupby("a", as_index=False).a) self.assertRaises(ValueError, lambda: psdf.groupby("a", as_index=False)["a"]) @@ -124,10 +126,16 @@ def sort(df): self.assertRaises(TypeError, lambda: psdf.a.groupby(psdf.b, as_index=False)) - self.assertRaises(NotImplementedError, lambda: psdf.groupby("a", axis=1)) - self.assertRaises(NotImplementedError, lambda: psdf.groupby("a", axis="columns")) - self.assertRaises(ValueError, lambda: psdf.groupby("a", "b")) - self.assertRaises(TypeError, lambda: psdf.a.groupby(psdf.a, psdf.b)) + if LooseVersion(pd.__version__) < "3.0.0": + self.assertRaises(NotImplementedError, lambda: psdf.groupby("a", axis=1)) + self.assertRaises(NotImplementedError, lambda: psdf.groupby("a", axis="columns")) + self.assertRaises(ValueError, lambda: psdf.groupby("a", "b")) + self.assertRaises(TypeError, lambda: psdf.a.groupby(psdf.a, psdf.b)) + else: + with self.assertRaises(TypeError): + psdf.groupby("a", axis=1) + with self.assertRaises(TypeError): + psdf.a.groupby(psdf.b, axis=1) # we can't use column name/names as a parameter `by` for `SeriesGroupBy`. self.assertRaises(KeyError, lambda: psdf.a.groupby(by="a")) From f546447195356ab5e838cd4170fb8fe16f7973ba Mon Sep 17 00:00:00 2001 From: Takuya Ueshin Date: Tue, 24 Feb 2026 12:15:16 -0800 Subject: [PATCH 015/130] [SPARK-55296][PS][FOLLOW-UP] Disconnect the anchor for more cases to mimic the CoW mode behavior ### What changes were proposed in this pull request? This is another follow-up of apache/spark#54375. Disconnects the anchor for more cases. ### Why are the changes needed? The anchor can be disconnect in most cases with pandas 3 to mimic the CoW mode behavior. ### Does this PR introduce _any_ user-facing change? Yes, it will behave more like pandas 3. ### How was this patch tested? The existing tests should pass. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54437 from ueshin/issues/SPARK-55296/cow_series. Authored-by: Takuya Ueshin Signed-off-by: Takuya Ueshin --- python/pyspark/pandas/frame.py | 5 ++++- python/pyspark/pandas/indexing.py | 12 ++++-------- python/pyspark/pandas/series.py | 16 ++++++++++++---- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/python/pyspark/pandas/frame.py b/python/pyspark/pandas/frame.py index aeb47709766ca..a9ffcbc9d59d0 100644 --- a/python/pyspark/pandas/frame.py +++ b/python/pyspark/pandas/frame.py @@ -663,7 +663,7 @@ def _update_internal_frame( self, internal: InternalFrame, check_same_anchor: bool = True, - anchor_force_disconnect: bool = False, + anchor_force_disconnect: Optional[bool] = None, ) -> None: """ Update InternalFrame with the given one. @@ -687,6 +687,9 @@ def _update_internal_frame( """ from pyspark.pandas.series import Series + if anchor_force_disconnect is None: + anchor_force_disconnect = LooseVersion(pd.__version__) >= "3.0.0" + if hasattr(self, "_psseries"): psseries = {} diff --git a/python/pyspark/pandas/indexing.py b/python/pyspark/pandas/indexing.py index f5f42b6fda891..7f26f4ce75956 100644 --- a/python/pyspark/pandas/indexing.py +++ b/python/pyspark/pandas/indexing.py @@ -636,7 +636,7 @@ def __setitem__(self, key: Any, value: Any) -> None: if self._psdf_or_psser.name is None: psser = psser.rename() - self._psdf_or_psser._psdf._update_internal_frame( + self._psdf_or_psser._update_internal_frame( psser._psdf[ self._psdf_or_psser._psdf._internal.column_labels ]._internal.resolved_copy, @@ -673,7 +673,7 @@ def __setitem__(self, key: Any, value: Any) -> None: internal = self._internal.with_new_spark_column( self._psdf_or_psser._column_label, scol # TODO: dtype? ) - self._psdf_or_psser._psdf._update_internal_frame(internal, check_same_anchor=False) + self._psdf_or_psser._update_internal_frame(internal, check_same_anchor=False) else: assert self._is_df @@ -821,11 +821,7 @@ def __setitem__(self, key: Any, value: Any) -> None: internal = self._internal.with_new_columns( new_data_spark_columns, column_labels=column_labels, data_fields=new_fields ) - self._psdf_or_psser._update_internal_frame( - internal, - check_same_anchor=False, - anchor_force_disconnect=LooseVersion(pd.__version__) >= "3.0.0", - ) + self._psdf_or_psser._update_internal_frame(internal, check_same_anchor=False) class LocIndexer(LocIndexerLike): @@ -1872,7 +1868,7 @@ def __setitem__(self, key: Any, value: Any) -> None: ) super().__setitem__(key, value) # Update again with resolved_copy to drop extra columns. - self._psdf._update_internal_frame( + self._psdf_or_psser._update_internal_frame( self._psdf._internal.resolved_copy, check_same_anchor=False ) diff --git a/python/pyspark/pandas/series.py b/python/pyspark/pandas/series.py index 3f8a2e57792da..1015ff4db4d94 100644 --- a/python/pyspark/pandas/series.py +++ b/python/pyspark/pandas/series.py @@ -495,6 +495,14 @@ def _internal(self) -> InternalFrame: def _column_label(self) -> Optional[Label]: return self._col_label + def _update_internal_frame( + self, internal: InternalFrame, check_same_anchor: bool = True + ) -> None: + if LooseVersion(pd.__version__) < "3.0.0": + self._psdf._update_internal_frame(internal, check_same_anchor=check_same_anchor) + else: + self._update_anchor(DataFrame(internal.select_column(self._column_label))) + def _update_anchor(self, psdf: DataFrame) -> None: assert psdf._internal.column_labels == [self._column_label], ( psdf._internal.column_labels, @@ -2220,7 +2228,7 @@ def _fillna_with_method( inplace = validate_bool_kwarg(inplace, "inplace") if inplace: - self._psdf._update_internal_frame(psser._psdf._internal, check_same_anchor=False) + self._update_internal_frame(psser._psdf._internal, check_same_anchor=False) return None else: return psser.copy() @@ -2529,7 +2537,7 @@ def clip( data_spark_columns=[scol.alias(self._internal.data_spark_column_names[0])], data_fields=[self._internal.data_fields[0]], ) - self._psdf._update_internal_frame(internal, check_same_anchor=False) + self._update_internal_frame(internal, check_same_anchor=False) return None else: return self._with_new_scol( @@ -5332,7 +5340,7 @@ def update(self, other: "Series") -> None: internal = self._psdf._internal.with_new_spark_column( self._column_label, scol # TODO: dtype? ) - self._psdf._update_internal_frame(internal) + self._update_internal_frame(internal) else: combined = combine_frames(self._psdf, other._psdf, how="leftouter") @@ -5349,7 +5357,7 @@ def update(self, other: "Series") -> None: self._column_label, scol # TODO: dtype? ) - self._psdf._update_internal_frame(internal.resolved_copy, check_same_anchor=False) + self._update_internal_frame(internal.resolved_copy, check_same_anchor=False) def where(self, cond: "Series", other: Any = np.nan) -> "Series": """ From 1e09fc872a32f41f4b136be9c45970db7cc14c8b Mon Sep 17 00:00:00 2001 From: Yicong-Huang <17627829+Yicong-Huang@users.noreply.github.com> Date: Tue, 24 Feb 2026 13:10:51 -0800 Subject: [PATCH 016/130] [SPARK-55600][PYTHON] Fix pandas to arrow loses row count when schema has 0 columns on classic ### What changes were proposed in this pull request? This PR fixes the row count loss issue when creating a Spark DataFrame from a pandas DataFrame with 0 columns in classic. The issue occurs due to PyArrow limitations when creating RecordBatches or Tables with 0 columns - row count information is lost. ### Why are the changes needed? Before this fix: ```python import pandas as pd from pyspark.sql.types import StructType pdf = pd.DataFrame(index=range(5)) # 5 rows, 0 columns df = spark.createDataFrame(pdf, schema=StructType([])) df.count() # Returns 0 (wrong!) ``` After this fix: ```python df.count() # Returns 5 (correct!) ``` ### Does this PR introduce _any_ user-facing change? Yes. Creating a DataFrame from a pandas DataFrame with 0 columns now correctly preserves the row count in Classic Spark. ### How was this patch tested? Added unit test `test_from_pandas_dataframe_with_zero_columns` in `test_creation.py` that tests both Arrow-enabled and Arrow-disabled paths. ### Was this patch authored or co-authored using generative AI tooling? No Closes #54382 from Yicong-Huang/SPARK-55600/fix/pandas-arrow-zero-columns-row-count. Authored-by: Yicong-Huang <17627829+Yicong-Huang@users.noreply.github.com> Signed-off-by: Takuya Ueshin --- python/pyspark/sql/pandas/conversion.py | 47 +++++++++++++++-------- python/pyspark/sql/tests/test_creation.py | 32 +++++++++++++++ 2 files changed, 62 insertions(+), 17 deletions(-) diff --git a/python/pyspark/sql/pandas/conversion.py b/python/pyspark/sql/pandas/conversion.py index cdcfcc872bbe2..5c4b6d14b24db 100644 --- a/python/pyspark/sql/pandas/conversion.py +++ b/python/pyspark/sql/pandas/conversion.py @@ -861,6 +861,12 @@ def convert_timestamp(value: Any) -> Any: ser.dt.to_pytimedelta(), index=ser.index, dtype="object", name=ser.name ) + # Handle the 0-column case separately to preserve row count + if len(pdf.columns) == 0: + from pyspark.sql import Row + + return [Row()] * len(pdf) + # Convert pandas.DataFrame to list of numpy records np_records = pdf.set_axis( [f"col_{i}" for i in range(len(pdf.columns))], axis="columns" @@ -998,16 +1004,21 @@ def _create_from_pandas_with_arrow( step = step if step > 0 else len(pdf) pdf_slices = (pdf.iloc[start : start + step] for start in range(0, len(pdf), step)) - # Create Arrow batches directly using the standalone function - arrow_batches = [ - create_arrow_batch_from_pandas( - [(c, t) for (_, c), t in zip(pdf_slice.items(), spark_types)], - timezone=timezone, - safecheck=safecheck, - prefers_large_types=prefers_large_var_types, - ) - for pdf_slice in pdf_slices - ] + # Handle the 0-column case separately to preserve row count. + # pa.RecordBatch.from_pandas preserves num_rows via pandas index metadata. + if len(pdf.columns) == 0: + arrow_batches = [pa.RecordBatch.from_pandas(pdf_slice) for pdf_slice in pdf_slices] + else: + # Create Arrow batches directly using the standalone function + arrow_batches = [ + create_arrow_batch_from_pandas( + [(c, t) for (_, c), t in zip(pdf_slice.items(), spark_types)], + timezone=timezone, + safecheck=safecheck, + prefers_large_types=prefers_large_var_types, + ) + for pdf_slice in pdf_slices + ] jsparkSession = self._jsparkSession @@ -1074,14 +1085,16 @@ def _create_from_arrow_table( if not isinstance(schema, StructType): schema = from_arrow_schema(table.schema, prefer_timestamp_ntz=prefer_timestamp_ntz) - table = _check_arrow_table_timestamps_localize(table, schema, True, timezone).cast( - to_arrow_schema( - schema, - error_on_duplicated_field_names_in_struct=True, - timezone="UTC", - prefers_large_types=prefers_large_var_types, + # Skip cast for 0-column tables as it loses row count + if len(schema.fields) > 0: + table = _check_arrow_table_timestamps_localize(table, schema, True, timezone).cast( + to_arrow_schema( + schema, + error_on_duplicated_field_names_in_struct=True, + timezone="UTC", + prefers_large_types=prefers_large_var_types, + ) ) - ) # Chunk the Arrow Table into RecordBatches chunk_size = arrow_batch_size diff --git a/python/pyspark/sql/tests/test_creation.py b/python/pyspark/sql/tests/test_creation.py index 906dab9692011..96abd8d1ffba1 100644 --- a/python/pyspark/sql/tests/test_creation.py +++ b/python/pyspark/sql/tests/test_creation.py @@ -261,6 +261,38 @@ def test_empty_schema(self): sdf = self.spark.createDataFrame(data, schema) assertDataFrameEqual(sdf, data) + @unittest.skipIf( + not have_pandas or not have_pyarrow, + pandas_requirement_message or pyarrow_requirement_message, + ) + def test_from_pandas_dataframe_with_zero_columns(self): + """SPARK-55600: Test that row count is preserved when creating DataFrame from + pandas with 0 columns but with explicit schema in classic Spark.""" + import pandas as pd + + # Create a pandas DataFrame with 5 rows but 0 columns + pdf = pd.DataFrame(index=range(5)) + schema = StructType([]) + + # Test with Arrow optimization enabled + with self.sql_conf( + { + "spark.sql.execution.arrow.pyspark.enabled": True, + "spark.sql.execution.arrow.pyspark.fallback.enabled": False, + } + ): + df = self.spark.createDataFrame(pdf, schema=schema) + self.assertEqual(df.schema, schema) + self.assertEqual(df.count(), 5) + self.assertEqual(len(df.collect()), 5) + + # Test with Arrow optimization disabled + with self.sql_conf({"spark.sql.execution.arrow.pyspark.enabled": False}): + df = self.spark.createDataFrame(pdf, schema=schema) + self.assertEqual(df.schema, schema) + self.assertEqual(df.count(), 5) + self.assertEqual(len(df.collect()), 5) + class DataFrameCreationTests( DataFrameCreationTestsMixin, From 4e55f6e93b819377558c73c5181144d99dca3981 Mon Sep 17 00:00:00 2001 From: Devin Petersohn Date: Wed, 25 Feb 2026 07:15:32 +0900 Subject: [PATCH 017/130] [SPARK-54666][PS] Leave numeric types unchanged on `to_numeric` ### What changes were proposed in this pull request? Fix a bug where numeric Series datatypes would change to float (and potentially lose precision) on `to_numeric`. ### Why are the changes needed? It is a bug, it doesn't match pandas behavior or user expectations. ### Does this PR introduce _any_ user-facing change? Yes, fix the bug ### How was this patch tested? CI ### Was this patch authored or co-authored using generative AI tooling? Co-authored-by: Claude Sonnet 4.5 Closes #54403 from devin-petersohn/devin/to_numeric_downcast. Authored-by: Devin Petersohn Signed-off-by: Hyukjin Kwon --- python/pyspark/pandas/namespace.py | 3 +++ python/pyspark/pandas/tests/test_namespace.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/python/pyspark/pandas/namespace.py b/python/pyspark/pandas/namespace.py index 2213bfcc6aa16..3ff617c0ee3fb 100644 --- a/python/pyspark/pandas/namespace.py +++ b/python/pyspark/pandas/namespace.py @@ -64,6 +64,7 @@ FloatType, DoubleType, BooleanType, + NumericType, TimestampType, TimestampNTZType, DecimalType, @@ -3651,6 +3652,8 @@ def to_numeric(arg, errors="raise"): 1.0 """ if isinstance(arg, Series): + if isinstance(arg.spark.data_type, (NumericType, BooleanType)): + return arg.copy() if errors == "coerce": spark_session = arg._internal.spark_frame.sparkSession if is_ansi_mode_enabled(spark_session): diff --git a/python/pyspark/pandas/tests/test_namespace.py b/python/pyspark/pandas/tests/test_namespace.py index 8a267f76c5369..f68a637723f79 100644 --- a/python/pyspark/pandas/tests/test_namespace.py +++ b/python/pyspark/pandas/tests/test_namespace.py @@ -607,6 +607,11 @@ def test_to_numeric(self): lambda: ps.to_numeric(psser, errors="ignore"), ) + # SPARK-54666: Series with numeric dtype should be returned as-is. + pser = pd.Series([-1554478299, 2]) + psser = ps.from_pandas(pser) + self.assert_eq(pd.to_numeric(pser), ps.to_numeric(psser)) + def test_json_normalize(self): # Basic test case with a simple JSON structure data = [ From f0285c489afa7a0fe03a9b19d582b19406da94c1 Mon Sep 17 00:00:00 2001 From: pranavdev022 Date: Wed, 25 Feb 2026 07:16:40 +0900 Subject: [PATCH 018/130] [SPARK-55636][CONNECT] Add detailed errors in case of deduplication of invalid columns ### What changes were proposed in this pull request? This PR updates the error handling for invalid deduplicate column names in Spark Connect to use the standard `UNRESOLVED_COLUMN_AMONG_FIELD_NAMES` error class instead of throwing INTERNAL_ERROR, a generic error message. Example | Classic | Connect (Before) | Connect (After) -- | -- | -- | -- image | Cannot resolve column name "artist_id" among (id, song_name, artist_name). | [[INTERNAL_ERROR](https://docs.databricks.com/error-messages/error-classes.html#internal_error)] Invalid deduplicate column artist_id SQLSTATE: XX000 | [[UNRESOLVED_COLUMN_AMONG_FIELD_NAMES](https://docs.databricks.com/error-messages/error-classes.html#unresolved_column_among_field_names)] Cannot resolve column name "artist_id" among (id, song_name, artist_name). SQLSTATE: 42703 image | Cannot resolve column name "cont.f1" among (id, cont). | [[INTERNAL_ERROR](https://docs.databricks.com/error-messages/error-classes.html#internal_error)] Invalid deduplicate column cont.f1 SQLSTATE: XX000 | [[UNRESOLVED_COLUMN_AMONG_FIELD_NAMES](https://docs.databricks.com/error-messages/error-classes.html#unresolved_column_among_field_names)] Cannot resolve column name "cont.f1" among (id, cont). SQLSTATE: 42703 image | works | works | works image | Cannot resolve column name "song.names" among (id, song.name, artist_name). | [[INTERNAL_ERROR](https://docs.databricks.com/error-messages/error-classes.html#internal_error)] Invalid deduplicate column song.names SQLSTATE: XX000 | [[UNRESOLVED_COLUMN_AMONG_FIELD_NAMES](https://docs.databricks.com/error-messages/error-classes.html#unresolved_column_among_field_names)] Cannot resolve column name "song.names" among (id, song.name, artist_name). SQLSTATE: 42703 image | works | works | works image | Cannot resolve column name "cont.value" among (id, cont.val). | [[INTERNAL_ERROR](https://docs.databricks.com/error-messages/error-classes.html#internal_error)] Invalid deduplicate column cont.value SQLSTATE: XX000 | [[UNRESOLVED_COLUMN_AMONG_FIELD_NAMES](https://docs.databricks.com/error-messages/error-classes.html#unresolved_column_among_field_names)] Cannot resolve column name "cont.value" among (id, cont.val). SQLSTATE: 42703 image | image | same | same ### Why are the changes needed? The previous error message in Spark Connect was not consistent with classic Spark and lacked helpful context. This change aligns Spark Connect error messages with classic Spark, providing users with: 1. The correct error class (`UNRESOLVED_COLUMN_AMONG_FIELD_NAMES` instead of `INTERNAL_ERROR`). 2. The correct SQLSTATE (42703 instead of XX000). 3. A list of available column names to help users fix the issue. ### Does this PR introduce _any_ user-facing change? Yes. Error messages for invalid deduplicate column names in Spark Connect are now more detailed and consistent with classic Spark. ### How was this patch tested? Tested with a custom image with the proposed changes. ### Was this patch authored or co-authored using generative AI tooling? No Closes #54422 from pranavdev022/dedup-errors-connect. Authored-by: pranavdev022 Signed-off-by: Hyukjin Kwon --- .../spark/sql/connect/planner/InvalidInputErrors.scala | 6 ++++-- .../spark/sql/connect/planner/SparkConnectPlanner.scala | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/InvalidInputErrors.scala b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/InvalidInputErrors.scala index 81c001ed839fe..f4a6913d1eab9 100644 --- a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/InvalidInputErrors.scala +++ b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/InvalidInputErrors.scala @@ -54,8 +54,10 @@ object InvalidInputErrors { InvalidPlanInput( "Deduplicate requires to either deduplicate on all columns or a subset of columns") - def invalidDeduplicateColumn(colName: String): InvalidPlanInput = - InvalidPlanInput(s"Invalid deduplicate column $colName") + def invalidDeduplicateColumn(colName: String, fieldNames: String): InvalidPlanInput = + InvalidPlanInput( + "UNRESOLVED_COLUMN_AMONG_FIELD_NAMES", + Map("colName" -> colName, "fieldNames" -> fieldNames)) def functionEvalTypeNotSupported(evalType: Int): InvalidPlanInput = InvalidPlanInput(s"Function with EvalType: $evalType is not supported") diff --git a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/SparkConnectPlanner.scala b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/SparkConnectPlanner.scala index 611e19b01b20a..ee8180d5e6f8b 100644 --- a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/SparkConnectPlanner.scala +++ b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/planner/SparkConnectPlanner.scala @@ -1445,7 +1445,8 @@ class SparkConnectPlanner( // so we call filter instead of find. val cols = allColumns.filter(col => resolver(col.name, colName)) if (cols.isEmpty) { - throw InvalidInputErrors.invalidDeduplicateColumn(colName) + val fieldNames = allColumns.map(_.name).mkString(", ") + throw InvalidInputErrors.invalidDeduplicateColumn(colName, fieldNames) } cols } From 8fd58ed005053632199522f75cef7e7d5242640a Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Tue, 24 Feb 2026 18:14:37 -0800 Subject: [PATCH 019/130] [SPARK-54276][BUILD] Bump Hadoop 3.4.3 ### What changes were proposed in this pull request? Upgrade Hadoop dependency to 3.4.3. ### Why are the changes needed? This release includes HADOOP-19212, which makes UGI work with Java 25. https://hadoop.apache.org/release/3.4.3.html ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Pass CI. Also verified `spark-sql` can successfully bootstrap on JDK 25 now ``` $ java -version openjdk version "25.0.1" 2025-10-21 LTS OpenJDK Runtime Environment Temurin-25.0.1+8 (build 25.0.1+8-LTS) OpenJDK 64-Bit Server VM Temurin-25.0.1+8 (build 25.0.1+8-LTS, mixed mode, sharing) $ build/sbt -Phive,hive-thriftserver clean package $ SPARK_PREPEND_CLASSES=true bin/spark-sql NOTE: SPARK_PREPEND_CLASSES is set, placing locally compiled Spark classes ahead of assembly. WARNING: Using incubator modules: jdk.incubator.vector WARNING: package sun.security.action not in java.base Using Spark's default log4j profile: org/apache/spark/log4j2-defaults.properties 26/01/28 17:23:22 WARN Utils: Your hostname, H27212-MAC-01.local, resolves to a loopback address: 127.0.0.1; using 10.242.159.140 instead (on interface en0) 26/01/28 17:23:22 WARN Utils: Set SPARK_LOCAL_IP if you need to bind to another address Using Spark's default log4j profile: org/apache/spark/log4j2-defaults.properties Setting default log level to "WARN". To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel). 26/01/28 17:23:23 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable WARNING: A terminally deprecated method in sun.misc.Unsafe has been called WARNING: sun.misc.Unsafe::arrayBaseOffset has been called by org.apache.spark.unsafe.Platform (file:/Users/chengpan/Projects/apache-spark/common/unsafe/target/scala-2.13/classes/) WARNING: Please consider reporting this to the maintainers of class org.apache.spark.unsafe.Platform WARNING: sun.misc.Unsafe::arrayBaseOffset will be removed in a future release 26/01/28 17:23:27 WARN ObjectStore: Version information not found in metastore. hive.metastore.schema.verification is not enabled so recording the schema version 2.3.0 26/01/28 17:23:27 WARN ObjectStore: setMetaStoreSchemaVersion called but recording version is disabled: version = 2.3.0, comment = Set by MetaStore chengpan127.0.0.1 26/01/28 17:23:27 WARN ObjectStore: Failed to get database default, returning NoSuchObjectException Spark Web UI available at http://10.242.159.140:4040 Spark master: local[*], Application Id: local-1769592205115 spark-sql (default)> select version(); 4.2.0 14557582199659d838bbaa7d7b182e5d92c3b907 Time taken: 1.376 seconds, Fetched 1 row(s) spark-sql (default)> ``` ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54029 from pan3793/SPARK-54276. Authored-by: Cheng Pan Signed-off-by: Dongjoon Hyun --- dev/deps/spark-deps-hadoop-3-hive-2.3 | 20 +++++++++---------- docs/building-spark.md | 2 +- pom.xml | 2 +- .../kubernetes/integration-tests/README.md | 4 ++-- .../hive/client/IsolatedClientLoader.scala | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/dev/deps/spark-deps-hadoop-3-hive-2.3 b/dev/deps/spark-deps-hadoop-3-hive-2.3 index 7f7039c7f0e64..fcb6983898fe7 100644 --- a/dev/deps/spark-deps-hadoop-3-hive-2.3 +++ b/dev/deps/spark-deps-hadoop-3-hive-2.3 @@ -68,16 +68,16 @@ gcs-connector/hadoop3-2.2.31/shaded/gcs-connector-hadoop3-2.2.31-shaded.jar gmetric4j/1.0.10//gmetric4j-1.0.10.jar gson/2.13.2//gson-2.13.2.jar guava/33.4.8-jre//guava-33.4.8-jre.jar -hadoop-aliyun/3.4.2//hadoop-aliyun-3.4.2.jar -hadoop-annotations/3.4.2//hadoop-annotations-3.4.2.jar -hadoop-aws/3.4.2//hadoop-aws-3.4.2.jar -hadoop-azure-datalake/3.4.2//hadoop-azure-datalake-3.4.2.jar -hadoop-azure/3.4.2//hadoop-azure-3.4.2.jar -hadoop-client-api/3.4.2//hadoop-client-api-3.4.2.jar -hadoop-client-runtime/3.4.2//hadoop-client-runtime-3.4.2.jar -hadoop-cloud-storage/3.4.2//hadoop-cloud-storage-3.4.2.jar -hadoop-huaweicloud/3.4.2//hadoop-huaweicloud-3.4.2.jar -hadoop-shaded-guava/1.4.0//hadoop-shaded-guava-1.4.0.jar +hadoop-aliyun/3.4.3//hadoop-aliyun-3.4.3.jar +hadoop-annotations/3.4.3//hadoop-annotations-3.4.3.jar +hadoop-aws/3.4.3//hadoop-aws-3.4.3.jar +hadoop-azure-datalake/3.4.3//hadoop-azure-datalake-3.4.3.jar +hadoop-azure/3.4.3//hadoop-azure-3.4.3.jar +hadoop-client-api/3.4.3//hadoop-client-api-3.4.3.jar +hadoop-client-runtime/3.4.3//hadoop-client-runtime-3.4.3.jar +hadoop-cloud-storage/3.4.3//hadoop-cloud-storage-3.4.3.jar +hadoop-huaweicloud/3.4.3//hadoop-huaweicloud-3.4.3.jar +hadoop-shaded-guava/1.5.0//hadoop-shaded-guava-1.5.0.jar hive-beeline/2.3.10//hive-beeline-2.3.10.jar hive-cli/2.3.10//hive-cli-2.3.10.jar hive-common/2.3.10//hive-common-2.3.10.jar diff --git a/docs/building-spark.md b/docs/building-spark.md index 57fa3c2bd6a43..1e7c28a273e84 100644 --- a/docs/building-spark.md +++ b/docs/building-spark.md @@ -83,7 +83,7 @@ You can enable the `yarn` profile and specify the exact version of Hadoop to com Example: - ./build/mvn -Pyarn -Dhadoop.version=3.4.1 -DskipTests clean package + ./build/mvn -Pyarn -Dhadoop.version=3.4.3 -DskipTests clean package ## Building With Hive and JDBC Support diff --git a/pom.xml b/pom.xml index 436edd65b8796..92221fee48506 100644 --- a/pom.xml +++ b/pom.xml @@ -127,7 +127,7 @@ 2.0.17 2.25.3 - 3.4.2 + 3.4.3 4.33.5 3.11.4 diff --git a/resource-managers/kubernetes/integration-tests/README.md b/resource-managers/kubernetes/integration-tests/README.md index d21c619c31b0a..8f50b9ca73546 100644 --- a/resource-managers/kubernetes/integration-tests/README.md +++ b/resource-managers/kubernetes/integration-tests/README.md @@ -136,8 +136,8 @@ properties to Maven. For example: mvn integration-test -am -pl :spark-kubernetes-integration-tests_2.13 \ -Pkubernetes -Pkubernetes-integration-tests \ - -Phadoop-3 -Dhadoop.version=3.4.0 \ - -Dspark.kubernetes.test.sparkTgz=spark-4.1.0-SNAPSHOT-bin-example.tgz \ + -Phadoop-3 -Dhadoop.version=3.4.3 \ + -Dspark.kubernetes.test.sparkTgz=spark-4.2.0-SNAPSHOT-bin-example.tgz \ -Dspark.kubernetes.test.imageTag=sometag \ -Dspark.kubernetes.test.imageRepo=docker.io/somerepo \ -Dspark.kubernetes.test.namespace=spark-int-tests \ diff --git a/sql/hive/src/main/scala/org/apache/spark/sql/hive/client/IsolatedClientLoader.scala b/sql/hive/src/main/scala/org/apache/spark/sql/hive/client/IsolatedClientLoader.scala index c439dfbd91692..8460bdd43fb06 100644 --- a/sql/hive/src/main/scala/org/apache/spark/sql/hive/client/IsolatedClientLoader.scala +++ b/sql/hive/src/main/scala/org/apache/spark/sql/hive/client/IsolatedClientLoader.scala @@ -65,7 +65,7 @@ private[hive] object IsolatedClientLoader extends Logging { case e: RuntimeException if e.getMessage.contains("hadoop") => // If the error message contains hadoop, it is probably because the hadoop // version cannot be resolved. - val fallbackVersion = "3.4.2" + val fallbackVersion = "3.4.3" logWarning(log"Failed to resolve Hadoop artifacts for the version " + log"${MDC(HADOOP_VERSION, hadoopVersion)}. We will change the hadoop version from " + log"${MDC(HADOOP_VERSION, hadoopVersion)} to " + From 954bb5765861ad1babb65f0490d228b50d33e857 Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Wed, 25 Feb 2026 10:33:41 +0800 Subject: [PATCH 020/130] [SPARK-55652][SQL] Optimize `VectorizedPlainValuesReader.readShorts()` with direct array access for heap buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? This PR optimizes `VectorizedPlainValuesReader.readShorts` by introducing a new batch write method `putShortsFromIntsLittleEndian` in `WritableColumnVector`, `OnHeapColumnVector`, and `OffHeapColumnVector`. In Parquet, `SHORT` values are stored as 4-byte little-endian integers. The previous implementation read each value individually via `ByteBuffer.getInt()` and called `putShort()` per element, incurring a virtual method dispatch per value and preventing JIT vectorization. The new approach: 1. Adds `putShortsFromIntsLittleEndian(int rowId, int count, byte[] src, int srcIndex)` as an abstract method in `WritableColumnVector`, with implementations in both `OnHeapColumnVector` and `OffHeapColumnVector`. 2. The implementations use `Platform.getInt` to read directly from the underlying `byte[]`, handle big-endian platforms by reversing bytes outside the loop, and write directly to `shortData[]` (OnHeap) or off-heap memory via `Platform.putShort` (OffHeap). 3. `readShorts` in `VectorizedPlainValuesReader` delegates to `putShortsFromIntsLittleEndian` when `buffer.hasArray()` is true, matching the pattern already established by `readIntegers`, `readLongs`, `readFloats`, and `readDoubles`. ### Why are the changes needed? The previous implementation of `readShorts` did not take advantage of the `hasArray()` fast path that other fixed-width type readers (`readIntegers`, `readLongs`, etc.) already use. This caused unnecessary overhead from: - Per-element virtual method dispatch via `putShort()` - `ByteBuffer.getInt()` overhead including internal bounds checking and byte-order branching on every call By pushing the batch operation into `WritableColumnVector` and operating directly on the underlying array, the JIT compiler can more effectively inline and vectorize the tight loop, eliminating these overheads for the common heap-buffer case. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? - Pass Github Actions and add a new test scenario in `ColumnarBatchSuite` to test `WritableColumnVector#putShortsFromIntsLittleEndian` - Rename the original code to `OldVectorizedPlainValuesReader`, and compare the latency of the old and new `readShorts` methods using JMH:
Benchmark Code (click to expand) ```java package org.apache.spark.sql.execution.datasources.parquet; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Random; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import org.apache.parquet.bytes.ByteBufferInputStream; import org.apache.spark.sql.execution.vectorized.OnHeapColumnVector; import org.apache.spark.sql.execution.vectorized.WritableColumnVector; import org.apache.spark.sql.types.DataTypes; BenchmarkMode(Mode.AverageTime) OutputTimeUnit(TimeUnit.MICROSECONDS) State(Scope.Thread) Fork(value = 1, jvmArgs = {"-Xms4G", "-Xmx4G"}) Warmup(iterations = 5, time = 1) Measurement(iterations = 10, time = 1) public class VectorizedPlainValuesReaderJMHBenchmark { // ==================== Parameters ==================== Param({"10000000"}) private int numValues; // ==================== Test Data ==================== private byte[] shortData; private static final int BATCH_SIZE = 4096; // Readers and streams for each scenario private VectorizedPlainValuesReader newSingleBufferOnHeapReader; private OldVectorizedPlainValuesReader oldSingleBufferOnHeapReader; private VectorizedPlainValuesReader newSingleBufferOffHeapReader; private OldVectorizedPlainValuesReader oldSingleBufferOffHeapReader; // ==================== State Classes ==================== State(Scope.Thread) public static class OnHeapColumnVectorState { public WritableColumnVector shortColumn; Setup(Level.Iteration) public void setup() { shortColumn = new OnHeapColumnVector(BATCH_SIZE, DataTypes.ShortType); } TearDown(Level.Iteration) public void tearDown() { shortColumn.close(); } Setup(Level.Invocation) public void reset() { shortColumn.reset(); } } // ==================== Setup ==================== Setup(Level.Trial) public void setupTrial() { Random random = new Random(42); shortData = generateShortData(numValues, random); } TearDown(Level.Trial) public void tearDownTrial() { } Setup(Level.Invocation) public void setupInvocation() throws IOException { // OnHeap SingleBuffer newSingleBufferOnHeapReader = new VectorizedPlainValuesReader(); newSingleBufferOnHeapReader.initFromPage(numValues, createSingleBufferInputStream(shortData)); oldSingleBufferOnHeapReader = new OldVectorizedPlainValuesReader(); oldSingleBufferOnHeapReader.initFromPage(numValues, createSingleBufferInputStream(shortData)); // OffHeap SingleBuffer newSingleBufferOffHeapReader = new VectorizedPlainValuesReader(); newSingleBufferOffHeapReader.initFromPage(numValues, createDirectSingleBufferInputStream(shortData)); oldSingleBufferOffHeapReader = new OldVectorizedPlainValuesReader(); oldSingleBufferOffHeapReader.initFromPage(numValues, createDirectSingleBufferInputStream(shortData)); } // ==================== Data Generation ==================== private byte[] generateShortData(int count, Random random) { ByteBuffer buffer = ByteBuffer.allocate(count * 4).order(ByteOrder.LITTLE_ENDIAN); for (int i = 0; i < count; i++) { buffer.putInt(random.nextInt(65536) - 32768); } return buffer.array(); } // ==================== ByteBufferInputStream Creation ==================== private ByteBufferInputStream createSingleBufferInputStream(byte[] data) { ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN); return ByteBufferInputStream.wrap(buffer); } private ByteBuffer createDirectBuffer(byte[] data) { ByteBuffer buffer = ByteBuffer.allocateDirect(data.length).order(ByteOrder.LITTLE_ENDIAN); buffer.put(data); buffer.flip(); return buffer; } private ByteBufferInputStream createDirectSingleBufferInputStream(byte[] data) { ByteBuffer buffer = createDirectBuffer(data); return ByteBufferInputStream.wrap(buffer); } // ==================================================================================== // readShorts OnHeap // ==================================================================================== Benchmark public void readShorts_onHeap_New(OnHeapColumnVectorState state) throws IOException { for (int i = 0; i < numValues; i += BATCH_SIZE) { newSingleBufferOnHeapReader.readShorts(Math.min(BATCH_SIZE, numValues - i), state.shortColumn, 0); } } Benchmark public void readShorts_onHeap_Old(OnHeapColumnVectorState state) throws IOException { for (int i = 0; i < numValues; i += BATCH_SIZE) { oldSingleBufferOnHeapReader.readShorts(Math.min(BATCH_SIZE, numValues - i), state.shortColumn, 0); } } // ==================================================================================== // readShorts offHeap // ==================================================================================== Benchmark public void readShorts_offHeap_New(OnHeapColumnVectorState state) throws IOException { for (int i = 0; i < numValues; i += BATCH_SIZE) { newSingleBufferOffHeapReader.readShorts(Math.min(BATCH_SIZE, numValues - i), state.shortColumn, 0); } } Benchmark public void readShorts_offHeap_Old(OnHeapColumnVectorState state) throws IOException { for (int i = 0; i < numValues; i += BATCH_SIZE) { oldSingleBufferOffHeapReader.readShorts(Math.min(BATCH_SIZE, numValues - i), state.shortColumn, 0); } } // ==================== Main Method ==================== public static void main(String[] args) throws RunnerException { String filter = args.length > 0 ? args[0] : VectorizedPlainValuesReaderJMHBenchmark.class.getSimpleName(); Options opt = new OptionsBuilder() .include(filter) .build(); new Runner(opt).run(); } } ```
Perform `build/sbt "sql/Test/runMain org.apache.spark.sql.execution.datasources.parquet.VectorizedPlainValuesReaderJMHBenchmark"` to conduct the test **Benchmark results:** - Java 17.0.18+8-LTS ``` Benchmark (numValues) Mode Cnt Score Error Units VectorizedPlainValuesReaderJMHBenchmark.readShorts_offHeap_New 10000000 avgt 10 4048.579 ± 54.466 us/op VectorizedPlainValuesReaderJMHBenchmark.readShorts_offHeap_Old 10000000 avgt 10 3952.443 ± 29.947 us/op VectorizedPlainValuesReaderJMHBenchmark.readShorts_onHeap_New 10000000 avgt 10 4358.785 ± 45.051 us/op VectorizedPlainValuesReaderJMHBenchmark.readShorts_onHeap_Old 10000000 avgt 10 6775.679 ± 75.302 us/op ``` - Java 21.0.10+7-LTS ``` VectorizedPlainValuesReaderJMHBenchmark.readShorts_offHeap_New 10000000 avgt 10 3050.606 ± 57.169 us/op VectorizedPlainValuesReaderJMHBenchmark.readShorts_offHeap_Old 10000000 avgt 10 7206.623 ± 29.275 us/op VectorizedPlainValuesReaderJMHBenchmark.readShorts_onHeap_New 10000000 avgt 10 3252.563 ± 44.564 us/op VectorizedPlainValuesReaderJMHBenchmark.readShorts_onHeap_Old 10000000 avgt 10 7145.537 ± 8.843 us/op ``` The test results reveal that the optimized OnHeap path achieves nearly 50%+ performance improvement. The OffHeap path shows no significant negative impact. ### Was this patch authored or co-authored using generative AI tooling? The benchmark code used for performance testing was generated by GitHub Copilot. Closes #54441 from LuciferYang/readShorts. Lead-authored-by: yangjie01 Co-authored-by: YangJie Signed-off-by: yangjie01 --- .../parquet/VectorizedPlainValuesReader.java | 9 +++++++-- .../vectorized/OffHeapColumnVector.java | 16 ++++++++++++++++ .../execution/vectorized/OnHeapColumnVector.java | 14 ++++++++++++++ .../vectorized/WritableColumnVector.java | 7 +++++++ .../vectorized/ColumnarBatchSuite.scala | 11 +++++++++++ 5 files changed, 55 insertions(+), 2 deletions(-) diff --git a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java index 7364fa5536c0d..a040a8990bad3 100644 --- a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java +++ b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java @@ -315,8 +315,13 @@ public final void readShorts(int total, WritableColumnVector c, int rowId) { int requiredBytes = total * 4; ByteBuffer buffer = getBuffer(requiredBytes); - for (int i = 0; i < total; i += 1) { - c.putShort(rowId + i, (short) buffer.getInt()); + if (buffer.hasArray()) { + int offset = buffer.arrayOffset() + buffer.position(); + c.putShortsFromIntsLittleEndian(rowId, total, buffer.array(), offset); + } else { + for (int i = 0; i < total; i += 1) { + c.putShort(rowId + i, (short) buffer.getInt()); + } } } diff --git a/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OffHeapColumnVector.java b/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OffHeapColumnVector.java index 42454b283d098..b56a49d8ee40d 100644 --- a/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OffHeapColumnVector.java +++ b/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OffHeapColumnVector.java @@ -267,6 +267,22 @@ public void putShorts(int rowId, int count, byte[] src, int srcIndex) { null, data + rowId * 2L, count * 2L); } + @Override + public void putShortsFromIntsLittleEndian(int rowId, int count, byte[] src, int srcIndex) { + int srcOffset = srcIndex + Platform.BYTE_ARRAY_OFFSET; + long dstOffset = data + rowId * 2L; + if (bigEndianPlatform) { + for (int i = 0; i < count; ++i, srcOffset += 4, dstOffset += 2) { + Platform.putShort(null, dstOffset, + (short) Integer.reverseBytes(Platform.getInt(src, srcOffset))); + } + } else { + for (int i = 0; i < count; ++i, srcOffset += 4, dstOffset += 2) { + Platform.putShort(null, dstOffset, (short) Platform.getInt(src, srcOffset)); + } + } + } + @Override public short getShort(int rowId) { if (dictionary == null) { diff --git a/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OnHeapColumnVector.java b/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OnHeapColumnVector.java index 401e499fee300..0854c42db672a 100644 --- a/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OnHeapColumnVector.java +++ b/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OnHeapColumnVector.java @@ -264,6 +264,20 @@ public void putShorts(int rowId, int count, byte[] src, int srcIndex) { Platform.SHORT_ARRAY_OFFSET + rowId * 2L, count * 2L); } + @Override + public void putShortsFromIntsLittleEndian(int rowId, int count, byte[] src, int srcIndex) { + int srcOffset = srcIndex + Platform.BYTE_ARRAY_OFFSET; + if (bigEndianPlatform) { + for (int i = 0; i < count; ++i, srcOffset += 4) { + shortData[rowId + i] = (short) Integer.reverseBytes(Platform.getInt(src, srcOffset)); + } + } else { + for (int i = 0; i < count; ++i, srcOffset += 4) { + shortData[rowId + i] = (short) Platform.getInt(src, srcOffset); + } + } + } + @Override public short getShort(int rowId) { if (dictionary == null) { diff --git a/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/WritableColumnVector.java b/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/WritableColumnVector.java index 904c48309778d..7ce4139df47b0 100644 --- a/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/WritableColumnVector.java +++ b/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/WritableColumnVector.java @@ -281,6 +281,13 @@ public void putBooleans(int rowId, int count, byte src, int srcIndex) { */ public abstract void putShorts(int rowId, int count, short[] src, int srcIndex); + /** + * Sets values from [src[srcIndex], src[srcIndex + count * 4]) to [rowId, rowId + count) + * Each 4-byte little endian int is truncated to a short. + */ + public abstract void putShortsFromIntsLittleEndian( + int rowId, int count, byte[] src, int srcIndex); + /** * Sets values from [src[srcIndex], src[srcIndex + count * 2]) to [rowId, rowId + count) * The data in src must be 2-byte platform native endian shorts. diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/vectorized/ColumnarBatchSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/vectorized/ColumnarBatchSuite.scala index 6d90bb985e269..0f2ca93f287c7 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/vectorized/ColumnarBatchSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/vectorized/ColumnarBatchSuite.scala @@ -323,6 +323,17 @@ class ColumnarBatchSuite extends SparkFunSuite { reference += 4 idx += 3 + val intSrc = Array(0, 1, 32767, -32768, 65535, -1, 12345, -12345) + val count = intSrc.length + val byteBuffer = ByteBuffer.allocate(count * 4).order(ByteOrder.LITTLE_ENDIAN) + intSrc.foreach(byteBuffer.putInt) + val byteArray = byteBuffer.array() + column.putShortsFromIntsLittleEndian(idx, count, byteArray, 0) + (0 until count).foreach { i => + reference += intSrc(i).toShort + } + idx += count + while (idx < column.capacity) { val single = random.nextBoolean() if (single) { From 1d43629af33bc3c3e1b089ee33965ab054d099d6 Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Wed, 25 Feb 2026 11:38:36 +0800 Subject: [PATCH 021/130] [SPARK-55678][BUILD] Add daily test for Java 25 ### What changes were proposed in this pull request? Add daily test for Java 25 by ``` $ cp .github/workflows/build_java21.yml .github/workflows/build_java25.yml ``` and replace 21 with 25. Don't expect all UT pass now, there are issues to fix. ### Why are the changes needed? Spark now basically works with JDK 25, and a daily CI helps us to find out remaining issues. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Monitor daily test reports after merging. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54472 from pan3793/SPARK-55678. Authored-by: Cheng Pan Signed-off-by: Cheng Pan --- .github/workflows/build_java25.yml | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 .github/workflows/build_java25.yml diff --git a/.github/workflows/build_java25.yml b/.github/workflows/build_java25.yml new file mode 100644 index 0000000000000..195fad5315ad4 --- /dev/null +++ b/.github/workflows/build_java25.yml @@ -0,0 +1,57 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +name: "Build / Java25 (master, Scala 2.13, Hadoop 3, JDK 25)" + +on: + schedule: + - cron: '0 4 * * *' + workflow_dispatch: + +jobs: + run-build: + permissions: + packages: write + name: Run + uses: ./.github/workflows/build_and_test.yml + if: github.repository == 'apache/spark' + with: + java: 25 + branch: master + hadoop: hadoop3 + envs: >- + { + "PYSPARK_IMAGE_TO_TEST": "python-311", + "PYTHON_TO_TEST": "python3.11", + "SKIP_MIMA": "true", + "SKIP_UNIDOC": "true", + "DEDICATED_JVM_SBT_TESTS": "org.apache.spark.sql.execution.datasources.parquet.ParquetFileFormatV1Suite,org.apache.spark.sql.execution.datasources.parquet.ParquetFileFormatV2Suite,org.apache.spark.sql.execution.datasources.orc.OrcSourceV1Suite,org.apache.spark.sql.execution.datasources.orc.OrcSourceV2Suite" + } + jobs: >- + { + "build": "true", + "pyspark": "true", + "sparkr": "true", + "tpcds-1g": "true", + "docker-integration-tests": "true", + "yarn": "true", + "k8s-integration-tests": "true", + "buf": "true", + "ui": "true" + } From 564f20b2b3aec690438b665eb321e95b880d9a43 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Tue, 24 Feb 2026 20:40:37 -0800 Subject: [PATCH 022/130] [SPARK-55677][BUILD] Upgrade `commons-cli` to 1.11.0 ### What changes were proposed in this pull request? This PR aims to upgrade `commons-cli` to 1.11.0. ### Why are the changes needed? To bring the latest bug fixes. - https://commons.apache.org/proper/commons-cli/changes.html#a1.11.0 ( 2025-11-08) - https://github.com/apache/commons-cli/pull/396 - https://github.com/apache/commons-cli/pull/411 ### Does this PR introduce _any_ user-facing change? No behavior change. ### How was this patch tested? Pass the CIs. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54471 from dongjoon-hyun/SPARK-55677. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- dev/deps/spark-deps-hadoop-3-hive-2.3 | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/deps/spark-deps-hadoop-3-hive-2.3 b/dev/deps/spark-deps-hadoop-3-hive-2.3 index fcb6983898fe7..bd79be555096d 100644 --- a/dev/deps/spark-deps-hadoop-3-hive-2.3 +++ b/dev/deps/spark-deps-hadoop-3-hive-2.3 @@ -35,7 +35,7 @@ bundle/2.35.4//bundle-2.35.4.jar cats-kernel_2.13/2.8.0//cats-kernel_2.13-2.8.0.jar chill-java/0.10.0//chill-java-0.10.0.jar chill_2.13/0.10.0//chill_2.13-0.10.0.jar -commons-cli/1.10.0//commons-cli-1.10.0.jar +commons-cli/1.11.0//commons-cli-1.11.0.jar commons-codec/1.21.0//commons-codec-1.21.0.jar commons-collections4/4.5.0//commons-collections4-4.5.0.jar commons-compiler/3.1.9//commons-compiler-3.1.9.jar diff --git a/pom.xml b/pom.xml index 92221fee48506..ff73a3041ebe5 100644 --- a/pom.xml +++ b/pom.xml @@ -212,7 +212,7 @@ 4.32.0 3.1.0 1.1.0 - 1.10.0 + 1.11.0 1.83 1.19.0 6.2.0 From a81fc2a65014b45940ced461e06f8b3e19f36b2f Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Wed, 25 Feb 2026 13:31:14 +0800 Subject: [PATCH 023/130] [SPARK-55670][BUILD] Add `-Dio.netty.noUnsafe=false` to enable Java 25 support ### What changes were proposed in this pull request? Arrow requires `-Dio.netty.noUnsafe=false` for Java 24+, see https://github.com/apache/arrow-java/issues/728 ### Why are the changes needed? To enable Java 25 support, especially for PySpark, which heavily uses Arrow for JVM/Python data exchange. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Manually verified with JDK 25 (we don't have JDK 25 CI yet), take one Arrow related UT as example. ``` $ export JAVA_HOME=/path/of/openjdk-25 $ build/sbt "sql/testOnly *ArrowConvertersSuite" ``` Before ``` [info] Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.ExceptionInInitializerError [in thread "Executor task launch worker for task 0.0 in stage 0.0 (TID 0)" [info] at org.apache.arrow.memory.netty.DefaultAllocationManagerFactory.(DefaultAllocationManagerFactory.java:26) [info] at java.base/java.lang.Class.forName0(Native Method) [info] at java.base/java.lang.Class.forName(Class.java:467) [info] at java.base/java.lang.Class.forName(Class.java:458) [info] at org.apache.arrow.memory.DefaultAllocationManagerOption.getFactory(DefaultAllocationManagerOption.java:105) [info] at org.apache.arrow.memory.DefaultAllocationManagerOption.getDefaultAllocationManagerFactory(DefaultAllocationManagerOption.java:92) [info] at org.apache.arrow.memory.BaseAllocator$Config.getAllocationManagerFactory(BaseAllocator.java:826) [info] at org.apache.arrow.memory.ImmutableConfig.access$001(ImmutableConfig.java:20) [info] at org.apache.arrow.memory.ImmutableConfig$InitShim.getAllocationManagerFactory(ImmutableConfig.java:80) [info] at org.apache.arrow.memory.ImmutableConfig.(ImmutableConfig.java:43) [info] at org.apache.arrow.memory.ImmutableConfig$Builder.build(ImmutableConfig.java:487) [info] at org.apache.arrow.memory.BaseAllocator.(BaseAllocator.java:72) [info] at org.apache.spark.sql.util.ArrowUtils$.(ArrowUtils.scala:36) ... [info] Run completed in 6 seconds, 326 milliseconds. [info] Total number of tests run: 26 [info] Suites: completed 0, aborted 1 [info] Tests: succeeded 0, failed 26, canceled 0, ignored 0, pending 0 [info] *** 1 SUITE ABORTED *** [info] *** 26 TESTS FAILED *** [error] Error during tests: [error] org.apache.spark.sql.execution.arrow.ArrowConvertersSuite [error] (Test / testOnly) sbt.TestsFailedException: Tests unsuccessful [error] Total time: 203 s (0:03:23.0), completed Feb 25, 2026, 10:39:52 AM ``` After ``` [info] Run completed in 7 seconds, 17 milliseconds. [info] Total number of tests run: 43 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 43, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. [success] Total time: 29 s, completed Feb 25, 2026, 10:41:46 AM ``` ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54470 from pan3793/SPARK-55670. Authored-by: Cheng Pan Signed-off-by: Cheng Pan --- .../main/java/org/apache/spark/launcher/JavaModuleOptions.java | 1 + pom.xml | 1 + project/SparkBuild.scala | 1 + sql/connect/bin/spark-connect-scala-client | 1 + 4 files changed, 4 insertions(+) diff --git a/launcher/src/main/java/org/apache/spark/launcher/JavaModuleOptions.java b/launcher/src/main/java/org/apache/spark/launcher/JavaModuleOptions.java index b42c7906fe18e..49c24bc887838 100644 --- a/launcher/src/main/java/org/apache/spark/launcher/JavaModuleOptions.java +++ b/launcher/src/main/java/org/apache/spark/launcher/JavaModuleOptions.java @@ -47,6 +47,7 @@ public class JavaModuleOptions { "-Dio.netty.tryReflectionSetAccessible=true", "-Dio.netty.allocator.type=pooled", "-Dio.netty.handler.ssl.defaultEndpointVerificationAlgorithm=NONE", + "-Dio.netty.noUnsafe=false", "--enable-native-access=ALL-UNNAMED"}; /** diff --git a/pom.xml b/pom.xml index ff73a3041ebe5..b73e440796634 100644 --- a/pom.xml +++ b/pom.xml @@ -335,6 +335,7 @@ -Dio.netty.tryReflectionSetAccessible=true -Dio.netty.allocator.type=pooled -Dio.netty.handler.ssl.defaultEndpointVerificationAlgorithm=NONE + -Dio.netty.noUnsafe=false --enable-native-access=ALL-UNNAMED 3.5.7 diff --git a/project/SparkBuild.scala b/project/SparkBuild.scala index ebd553e400e21..674d97c160866 100644 --- a/project/SparkBuild.scala +++ b/project/SparkBuild.scala @@ -1876,6 +1876,7 @@ object TestSettings { "-Dio.netty.tryReflectionSetAccessible=true", "-Dio.netty.allocator.type=pooled", "-Dio.netty.handler.ssl.defaultEndpointVerificationAlgorithm=NONE", + "-Dio.netty.noUnsafe=false", "--enable-native-access=ALL-UNNAMED").mkString(" ") s"-Xmx$heapSize -Xss4m -XX:MaxMetaspaceSize=$metaspaceSize -XX:ReservedCodeCacheSize=128m -Dfile.encoding=UTF-8 $extraTestJavaArgs" .split(" ").toSeq diff --git a/sql/connect/bin/spark-connect-scala-client b/sql/connect/bin/spark-connect-scala-client index 7f90353cc39b7..085f7e92f3c21 100755 --- a/sql/connect/bin/spark-connect-scala-client +++ b/sql/connect/bin/spark-connect-scala-client @@ -73,6 +73,7 @@ JVM_ARGS="-XX:+IgnoreUnrecognizedVMOptions \ -Dio.netty.tryReflectionSetAccessible=true \ -Dio.netty.allocator.type=pooled \ -Dio.netty.handler.ssl.defaultEndpointVerificationAlgorithm=NONE \ + -Dio.netty.noUnsafe=false \ --enable-native-access=ALL-UNNAMED \ $SCJVM_ARGS" From 32c3b666da7b0f4deb7463312b106e5ceeed5442 Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Wed, 25 Feb 2026 13:53:04 +0800 Subject: [PATCH 024/130] [SPARK-55678][BUILD][FOLLOWUP] Add Maven Java 25 daily CI and update badges ### What changes were proposed in this pull request? - Add Maven Java 25 daily CI - Update pipeline badges in README ### Why are the changes needed? Address comments https://github.com/apache/spark/pull/54472#issuecomment-3956562070 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Review and monitor CI status after merging. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54474 from pan3793/SPARK-55678-followup. Authored-by: Cheng Pan Signed-off-by: yangjie01 --- .github/workflows/build_maven_java25.yml | 35 ++++++++++++++++++++++++ README.md | 4 ++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build_maven_java25.yml diff --git a/.github/workflows/build_maven_java25.yml b/.github/workflows/build_maven_java25.yml new file mode 100644 index 0000000000000..8c99ac426b99b --- /dev/null +++ b/.github/workflows/build_maven_java25.yml @@ -0,0 +1,35 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +name: "Build / Maven (master, Scala 2.13, Hadoop 3, JDK 25)" + +on: + schedule: + - cron: '0 14 * * *' + workflow_dispatch: + +jobs: + run-build: + permissions: + packages: write + name: Run + uses: ./.github/workflows/maven_test.yml + if: github.repository == 'apache/spark' + with: + java: 25 diff --git a/README.md b/README.md index 4d70f632fdb5d..19b80c9e6b155 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,14 @@ This README file only contains basic setup instructions. | | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/publish_snapshot.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/publish_snapshot.yml) | | | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_infra_images_cache.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_infra_images_cache.yml) | | | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_java21.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_java21.yml) | +| | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_java25.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_java25.yml) | | | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_non_ansi.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_non_ansi.yml) | | | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_uds.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_uds.yml) | | | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_rockdb_as_ui_backend.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_rockdb_as_ui_backend.yml) | | | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_maven.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_maven.yml) | | | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_maven_java21.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_maven_java21.yml) | -| | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_maven_java21_macos26.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_maven_java21_macos26.yml) | +| | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_maven_java25.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_maven_java25.yml) | +| | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_maven_java21_macos26.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_maven_java21_macos26.yml) | | | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_maven_java21_arm.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_maven_java21_arm.yml) | | | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_coverage.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_coverage.yml) | | | [![GitHub Actions Build](https://github.com/apache/spark/actions/workflows/build_python_pypy3.10.yml/badge.svg)](https://github.com/apache/spark/actions/workflows/build_python_pypy3.10.yml) | From 054cca128333d76a3f70bb75a76c3bab612dc01f Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Wed, 25 Feb 2026 14:29:30 +0800 Subject: [PATCH 025/130] [SPARK-55656][BUILD] Upgrade Guava to 33.5.0-jre ### What changes were proposed in this pull request? This pr aims to upgrade Guava from 33.4.8 to 33.5.0. ### Why are the changes needed? The new version brings some Improvements, such as - cache: [Improved the handling of exceptions from compute functions in Cache.asMap(). ](https://github.com/google/guava/commit/087f2c4a8012fb1256f80f6f776df0e8706af683) - collect: [Improved Iterators.mergeSorted() to preserve stability for equal elements](https://github.com/google/guava/commit/4dc93be9a8f85ea7bc751fd6cc6f2b07ab327dea). The full release notes as follows: - https://github.com/google/guava/releases/tag/v33.5.0 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? - Pass Github Actions ### Was this patch authored or co-authored using generative AI tooling? No Closes #54447 from LuciferYang/SPARK-55656. Lead-authored-by: yangjie01 Co-authored-by: YangJie Signed-off-by: yangjie01 --- dev/deps/spark-deps-hadoop-3-hive-2.3 | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/deps/spark-deps-hadoop-3-hive-2.3 b/dev/deps/spark-deps-hadoop-3-hive-2.3 index bd79be555096d..9a0fc1f363f16 100644 --- a/dev/deps/spark-deps-hadoop-3-hive-2.3 +++ b/dev/deps/spark-deps-hadoop-3-hive-2.3 @@ -67,7 +67,7 @@ flatbuffers-java/25.2.10//flatbuffers-java-25.2.10.jar gcs-connector/hadoop3-2.2.31/shaded/gcs-connector-hadoop3-2.2.31-shaded.jar gmetric4j/1.0.10//gmetric4j-1.0.10.jar gson/2.13.2//gson-2.13.2.jar -guava/33.4.8-jre//guava-33.4.8-jre.jar +guava/33.5.0-jre//guava-33.5.0-jre.jar hadoop-aliyun/3.4.3//hadoop-aliyun-3.4.3.jar hadoop-annotations/3.4.3//hadoop-annotations-3.4.3.jar hadoop-aws/3.4.3//hadoop-aws-3.4.3.jar diff --git a/pom.xml b/pom.xml index b73e440796634..353381376144c 100644 --- a/pom.xml +++ b/pom.xml @@ -197,7 +197,7 @@ 2.13.1 4.1.17 - 33.4.8-jre + 33.5.0-jre 1.0.3 2.13.2 3.1.9 From b29324602b038489bde38c57794c2d4e228634f2 Mon Sep 17 00:00:00 2001 From: Takuya Ueshin Date: Wed, 25 Feb 2026 15:55:57 +0900 Subject: [PATCH 026/130] [SPARK-55675][PS][TESTS] Fix tests for window functions ### What changes were proposed in this pull request? Fixes tests for window functions. ### Why are the changes needed? There are test failures related to window functions. - `pyspark.pandas.tests.frame.test_interpolate` - `pyspark.pandas.tests.series.test_interpolate` - `pyspark.pandas.tests.window.test_expanding_adv` ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Updated the related tests. ### Was this patch authored or co-authored using generative AI tooling? Codex (GPT-5.3-Codex) Closes #54469 from ueshin/issues/SPARK-55675/window. Authored-by: Takuya Ueshin Signed-off-by: Hyukjin Kwon --- .../pandas/tests/frame/test_interpolate.py | 28 +++++++++++++------ .../pandas/tests/series/test_interpolate.py | 28 +++++++++++++------ .../pandas/tests/window/test_expanding.py | 15 ++++++---- .../pandas/tests/window/test_expanding_adv.py | 11 ++++++-- 4 files changed, 57 insertions(+), 25 deletions(-) diff --git a/python/pyspark/pandas/tests/frame/test_interpolate.py b/python/pyspark/pandas/tests/frame/test_interpolate.py index d61addb3dcc50..2b65d09f006de 100644 --- a/python/pyspark/pandas/tests/frame/test_interpolate.py +++ b/python/pyspark/pandas/tests/frame/test_interpolate.py @@ -18,6 +18,7 @@ import pandas as pd import pyspark.pandas as ps +from pyspark.loose_version import LooseVersion from pyspark.testing.pandasutils import PandasOnSparkTestCase, TestUtils @@ -35,14 +36,25 @@ def _test_interpolate(self, pobj): (4, "backward", "inside"), (5, "both", "inside"), ]: - self.assert_eq( - psobj.interpolate( - limit=limit, limit_direction=limit_direction, limit_area=limit_area - ).sort_index(), - pobj.interpolate( - limit=limit, limit_direction=limit_direction, limit_area=limit_area - ).sort_index(), - ) + # pandas 3.0.0 can raise when limit >= len(obj) in interpolate edge cases. + effective_limit = limit + if LooseVersion(pd.__version__) >= "3.0.0": + effective_limit = min(limit, len(pobj) - 1) + with self.subTest( + limit=effective_limit, limit_direction=limit_direction, limit_area=limit_area + ): + self.assert_eq( + psobj.interpolate( + limit=effective_limit, + limit_direction=limit_direction, + limit_area=limit_area, + ).sort_index(), + pobj.interpolate( + limit=effective_limit, + limit_direction=limit_direction, + limit_area=limit_area, + ).sort_index(), + ) def test_interpolate(self): pdf = pd.DataFrame( diff --git a/python/pyspark/pandas/tests/series/test_interpolate.py b/python/pyspark/pandas/tests/series/test_interpolate.py index 57b6a57f6c620..87155f9f33b85 100644 --- a/python/pyspark/pandas/tests/series/test_interpolate.py +++ b/python/pyspark/pandas/tests/series/test_interpolate.py @@ -18,6 +18,7 @@ import pandas as pd import pyspark.pandas as ps +from pyspark.loose_version import LooseVersion from pyspark.testing.pandasutils import PandasOnSparkTestCase @@ -35,14 +36,25 @@ def _test_interpolate(self, pobj): (4, "backward", "inside"), (5, "both", "inside"), ]: - self.assert_eq( - psobj.interpolate( - limit=limit, limit_direction=limit_direction, limit_area=limit_area - ).sort_index(), - pobj.interpolate( - limit=limit, limit_direction=limit_direction, limit_area=limit_area - ).sort_index(), - ) + # pandas 3.0.0 can raise when limit >= len(obj) in interpolate edge cases. + effective_limit = limit + if LooseVersion(pd.__version__) >= "3.0.0": + effective_limit = min(limit, len(pobj) - 1) + with self.subTest( + limit=effective_limit, limit_direction=limit_direction, limit_area=limit_area + ): + self.assert_eq( + psobj.interpolate( + limit=effective_limit, + limit_direction=limit_direction, + limit_area=limit_area, + ).sort_index(), + pobj.interpolate( + limit=effective_limit, + limit_direction=limit_direction, + limit_area=limit_area, + ).sort_index(), + ) def test_interpolate(self): pser = pd.Series( diff --git a/python/pyspark/pandas/tests/window/test_expanding.py b/python/pyspark/pandas/tests/window/test_expanding.py index 61e9f48a8a2f7..90b8803881b15 100644 --- a/python/pyspark/pandas/tests/window/test_expanding.py +++ b/python/pyspark/pandas/tests/window/test_expanding.py @@ -23,17 +23,18 @@ class ExpandingTestingFuncMixin: - def _test_expanding_func(self, ps_func, pd_func=None): + def _test_expanding_func(self, ps_func, pd_func=None, *, int_almost=False, float_almost=False): if not pd_func: pd_func = ps_func if isinstance(pd_func, str): pd_func = self.convert_str_to_lambda(pd_func) if isinstance(ps_func, str): ps_func = self.convert_str_to_lambda(ps_func) + pser = pd.Series([1, 2, 3, 7, 9, 8], index=np.random.rand(6), name="a") psser = ps.from_pandas(pser) - self.assert_eq(ps_func(psser.expanding(2)), pd_func(pser.expanding(2)), almost=True) - self.assert_eq(ps_func(psser.expanding(2)), pd_func(pser.expanding(2)), almost=True) + self.assert_eq(ps_func(psser.expanding(2)), pd_func(pser.expanding(2)), almost=int_almost) + self.assert_eq(ps_func(psser.expanding(2)), pd_func(pser.expanding(2)), almost=int_almost) # Multiindex pser = pd.Series( @@ -46,14 +47,16 @@ def _test_expanding_func(self, ps_func, pd_func=None): {"a": [1.0, 2.0, 3.0, 2.0], "b": [4.0, 2.0, 3.0, 1.0]}, index=np.random.rand(4) ) psdf = ps.from_pandas(pdf) - self.assert_eq(ps_func(psdf.expanding(2)), pd_func(pdf.expanding(2))) - self.assert_eq(ps_func(psdf.expanding(2)).sum(), pd_func(pdf.expanding(2)).sum()) + self.assert_eq(ps_func(psdf.expanding(2)), pd_func(pdf.expanding(2)), almost=float_almost) + self.assert_eq( + ps_func(psdf.expanding(2)).sum(), pd_func(pdf.expanding(2)).sum(), almost=float_almost + ) # Multiindex column columns = pd.MultiIndex.from_tuples([("a", "x"), ("a", "y")]) pdf.columns = columns psdf.columns = columns - self.assert_eq(ps_func(psdf.expanding(2)), pd_func(pdf.expanding(2))) + self.assert_eq(ps_func(psdf.expanding(2)), pd_func(pdf.expanding(2)), almost=float_almost) class ExpandingMixin(ExpandingTestingFuncMixin): diff --git a/python/pyspark/pandas/tests/window/test_expanding_adv.py b/python/pyspark/pandas/tests/window/test_expanding_adv.py index 5ee43f97e6fbb..554c11e46b22d 100644 --- a/python/pyspark/pandas/tests/window/test_expanding_adv.py +++ b/python/pyspark/pandas/tests/window/test_expanding_adv.py @@ -15,6 +15,9 @@ # limitations under the License. # +import pandas as pd + +from pyspark.loose_version import LooseVersion from pyspark.testing.pandasutils import PandasOnSparkTestCase from pyspark.pandas.tests.window.test_expanding import ExpandingTestingFuncMixin @@ -27,13 +30,15 @@ def test_expanding_std(self): self._test_expanding_func("std") def test_expanding_var(self): - self._test_expanding_func("var") + self._test_expanding_func("var", int_almost=True) def test_expanding_skew(self): - self._test_expanding_func("skew") + self._test_expanding_func("skew", int_almost=True) def test_expanding_kurt(self): - self._test_expanding_func("kurt") + self._test_expanding_func( + "kurt", int_almost=True, float_almost=LooseVersion(pd.__version__) >= "3.0.0" + ) class ExpandingAdvTests( From 8ac083c08ef8ca4b1d7d1baa84b20fbc119adbeb Mon Sep 17 00:00:00 2001 From: Yicong-Huang <17627829+Yicong-Huang@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:56:27 +0900 Subject: [PATCH 027/130] [SPARK-55674][PYTHON] Optimize 0-column table conversion in Spark Connect ### What changes were proposed in this pull request? Replace `pa.Table.from_struct_array(pa.array([{}] * len(data), type=pa.struct([])))` with `pa.Table.from_batches([pa.RecordBatch.from_pandas(data)])` in `connect/session.py` when handling 0-column pandas DataFrames. This is O(1) operation, regardless how many rows are there. ### Why are the changes needed? The original approach constructs `len(data)` Python dict objects (`[{}] * len(data)`), which is O(n). `pa.RecordBatch.from_pandas` is an O(1) operation regardless of the number of rows, as it reads row count directly from pandas index metadata without allocating per-row Python objects. ### Does this PR introduce any user-facing change? No. ### How was this patch tested? Existing tests. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54468 from Yicong-Huang/SPARK-55674/followup/unify-zero-column-pandas-arrow-fix. Authored-by: Yicong-Huang <17627829+Yicong-Huang@users.noreply.github.com> Signed-off-by: Hyukjin Kwon --- python/pyspark/sql/connect/session.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/pyspark/sql/connect/session.py b/python/pyspark/sql/connect/session.py index 384d10c2ae585..f9a360ec6054f 100644 --- a/python/pyspark/sql/connect/session.py +++ b/python/pyspark/sql/connect/session.py @@ -622,8 +622,9 @@ def createDataFrame( safecheck = configs["spark.sql.execution.pandas.convertToArrowArraySafely"] # Handle the 0-column case separately to preserve row count. + # pa.RecordBatch.from_pandas preserves num_rows via pandas index metadata. if len(data.columns) == 0: - _table = pa.Table.from_struct_array(pa.array([{}] * len(data), type=pa.struct([]))) + _table = pa.Table.from_batches([pa.RecordBatch.from_pandas(data)]) else: _table = pa.Table.from_batches( [ From 3e4df1c1c1e1d9f594a6afcf29b3bae05cc8a348 Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Tue, 24 Feb 2026 23:03:59 -0800 Subject: [PATCH 028/130] [SPARK-55679][CORE] Fix dectecting `sun.io.serialization.extendedDebugInfo` on Java 25 ### What changes were proposed in this pull request? Fix reading system property `sun.io.serialization.extendedDebugInfo` on Java 24+ ### Why are the changes needed? To enable Java 25 support. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? ``` $ export JAVA_HOME=/path/of/openjdk-25 $ build/sbt clean "core/testOnly *SerializationDebuggerSuite" ``` Before ``` [info] Cause: java.lang.ClassNotFoundException: sun.security.action.GetBooleanAction [info] at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580) [info] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490) [info] at java.base/java.lang.Class.forName0(Native Method) [info] at java.base/java.lang.Class.forName(Class.java:547) [info] at org.apache.spark.util.SparkClassUtils.classForName(SparkClassUtils.scala:42) [info] at org.apache.spark.util.SparkClassUtils.classForName$(SparkClassUtils.scala:37) [info] at org.apache.spark.util.SparkClassUtils$.classForName(SparkClassUtils.scala:169) [info] at org.apache.spark.serializer.SerializationDebugger$.(SerializationDebugger.scala:74) [info] Run completed in 918 milliseconds. [info] Total number of tests run: 0 [info] Suites: completed 0, aborted 1 [info] Tests: succeeded 0, failed 0, canceled 0, ignored 0, pending 0 [info] *** 1 SUITE ABORTED *** [error] Error during tests: [error] org.apache.spark.serializer.SerializationDebuggerSuite [error] (core / Test / testOnly) sbt.TestsFailedException: Tests unsuccessful [error] Total time: 66 s (0:01:06.0), completed Feb 25, 2026, 11:25:57 AM ``` After ``` [info] Run completed in 1 second, 26 milliseconds. [info] Total number of tests run: 22 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 22, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. [success] Total time: 61 s (0:01:01.0), completed Feb 25, 2026, 11:33:41 AM ``` ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54473 from pan3793/SPARK-55679. Authored-by: Cheng Pan Signed-off-by: Dongjoon Hyun --- .../serializer/SerializationDebugger.scala | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/core/src/main/scala/org/apache/spark/serializer/SerializationDebugger.scala b/core/src/main/scala/org/apache/spark/serializer/SerializationDebugger.scala index da08635eca4c5..21ecd05ebe32d 100644 --- a/core/src/main/scala/org/apache/spark/serializer/SerializationDebugger.scala +++ b/core/src/main/scala/org/apache/spark/serializer/SerializationDebugger.scala @@ -20,14 +20,12 @@ package org.apache.spark.serializer import java.io._ import java.lang.invoke.MethodHandles import java.lang.reflect.{Field, Method} -import java.security.{AccessController, PrivilegedAction} import scala.annotation.tailrec import scala.collection.mutable import scala.util.control.NonFatal import org.apache.spark.internal.Logging -import org.apache.spark.util.SparkClassUtils private[spark] object SerializationDebugger extends Logging { @@ -69,15 +67,20 @@ private[spark] object SerializationDebugger extends Logging { new SerializationDebugger().visit(obj, List.empty) } - private[serializer] var enableDebugging: Boolean = { - val lookup = MethodHandles.lookup() - val clazz = SparkClassUtils.classForName("sun.security.action.GetBooleanAction") - val constructor = clazz.getConstructor(classOf[String]) - val mh = lookup.unreflectConstructor(constructor) - val action = mh.invoke("sun.io.serialization.extendedDebugInfo") - .asInstanceOf[PrivilegedAction[Boolean]] - !AccessController.doPrivileged(action).booleanValue() - } + private[serializer] var enableDebugging: Boolean = + if (Runtime.version().feature() >= 24) { + // Access plain system property on modern JDKs. + // https://github.com/openjdk/jdk/commit/9b0ab92b16f682e65e9847e8127b6ce09fc5759c + !java.lang.Boolean.getBoolean("sun.io.serialization.extendedDebugInfo") + } else { + // Try to access the private static boolean ObjectOutputStream.extendedDebugInfo + // to avoid handling SecurityManager changes across different version of JDKs. + // See details at - JEP 486: Permanently Disable the Security Manager (JDK 24) + val clazz = classOf[ObjectOutputStream] + val lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup()) + val vh = lookup.findStaticVarHandle(clazz, "extendedDebugInfo", java.lang.Boolean.TYPE) + !vh.get().asInstanceOf[Boolean] + } private class SerializationDebugger { From 0e2726543a4cb709820c57509fc7236bf8a98ffa Mon Sep 17 00:00:00 2001 From: Szehon Ho Date: Wed, 25 Feb 2026 17:03:35 +0800 Subject: [PATCH 029/130] [SPARK-55673][SQL] Add more tests for nested type encoder ### What changes were proposed in this pull request? Small follow up for https://github.com/apache/spark/pull/52444 to add some more tests to reproduce the issue ### Why are the changes needed? There were tests added in JavaDataSetSuite but they didnt reproduce the issue, I had missed adding these tests ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Ran tests ### Was this patch authored or co-authored using generative AI tooling? No Closes #54466 from szehon-ho/more_encoder_test. Authored-by: Szehon Ho Signed-off-by: Wenchen Fan --- .../sql/catalyst/JavaTypeInferenceBeans.java | 12 +++---- .../apache/spark/sql/JavaDatasetSuite.java | 35 +++++++++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/JavaTypeInferenceBeans.java b/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/JavaTypeInferenceBeans.java index 3e4cade6c8d1e..e991a508e0b6f 100644 --- a/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/JavaTypeInferenceBeans.java +++ b/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/JavaTypeInferenceBeans.java @@ -80,7 +80,7 @@ static class JavaBeanWithGenericHierarchy extends JavaBeanWithGenericsABC { + public static class Foo { private T t; public T getT() { @@ -92,7 +92,7 @@ public void setT(T t) { } } - static class FooWrapper { + public static class FooWrapper { private Foo foo; public Foo getFoo() { @@ -104,14 +104,14 @@ public void setFoo(Foo foo) { } } - static class StringFooWrapper extends FooWrapper { + public static class StringFooWrapper extends FooWrapper { } // SPARK-46679: Additional test classes for same type variable names at different levels - static class StringBarWrapper extends BarWrapper { + public static class StringBarWrapper extends BarWrapper { } - static class BarWrapper { + public static class BarWrapper { private Bar bar; public Bar getBar() { @@ -123,7 +123,7 @@ public void setBar(Bar bar) { } } - static class Bar { + public static class Bar { private T t; public T getT() { diff --git a/sql/core/src/test/java/test/org/apache/spark/sql/JavaDatasetSuite.java b/sql/core/src/test/java/test/org/apache/spark/sql/JavaDatasetSuite.java index 83f477ecbe7ba..5b1f98475d51d 100644 --- a/sql/core/src/test/java/test/org/apache/spark/sql/JavaDatasetSuite.java +++ b/sql/core/src/test/java/test/org/apache/spark/sql/JavaDatasetSuite.java @@ -47,6 +47,7 @@ import org.apache.spark.sql.catalyst.expressions.GenericRow; import org.apache.spark.sql.test.TestSparkSession; import org.apache.spark.sql.types.StructType; +import org.apache.spark.sql.catalyst.JavaTypeInferenceBeans; import org.apache.spark.util.LongAccumulator; import static org.apache.spark.sql.functions.*; @@ -2110,6 +2111,40 @@ public Row call(Long i) { Assertions.assertEquals(expected, df.collectAsList()); } + @Test + public void testNestedEncoder() { + JavaTypeInferenceBeans.Foo foo = new JavaTypeInferenceBeans.Foo<>(); + foo.setT("test value"); + + JavaTypeInferenceBeans.StringFooWrapper wrapper = new JavaTypeInferenceBeans.StringFooWrapper(); + wrapper.setFoo(foo); + + List data = Arrays.asList(wrapper); + Dataset ds = + spark.createDataset(data, Encoders.bean(JavaTypeInferenceBeans.StringFooWrapper.class)); + + List result = ds.collectAsList(); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals("test value", result.get(0).getFoo().getT()); + } + + @Test + public void testNestedEncoder2() { + JavaTypeInferenceBeans.Bar bar = new JavaTypeInferenceBeans.Bar<>(); + bar.setT("test value"); + + JavaTypeInferenceBeans.StringBarWrapper wrapper = new JavaTypeInferenceBeans.StringBarWrapper(); + wrapper.setBar(bar); + + List data = Arrays.asList(wrapper); + Dataset ds = + spark.createDataset(data, Encoders.bean(JavaTypeInferenceBeans.StringBarWrapper.class)); + + List result = ds.collectAsList(); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals("test value", result.get(0).getBar().getT()); + } + public static class BeanWithSet implements Serializable { private Set fields; From dd22010c7a781bf4bb073bb44c6dacfce92c614a Mon Sep 17 00:00:00 2001 From: Tim Lee Date: Wed, 25 Feb 2026 17:52:23 +0800 Subject: [PATCH 030/130] [SPARK-55681][SQL] Fix singleton DataType equality after deserialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? Override `equals()` and `hashCode()` on 14 singleton `DataType` classes so that non-singleton instances compare equal to the case object singletons: ``` BinaryType, BooleanType, ByteType, ShortType, IntegerType, LongType, FloatType, DoubleType, DateType, TimestampType, TimestampNTZType, NullType, CalendarIntervalType, VariantType ``` For each type: ``` override def equals(obj: Any): Boolean = obj.isInstanceOf[XType] override def hashCode(): Int = classOf[XType].getSimpleName.hashCode ``` `getSimpleName` is used because Scala's auto-generated hashCode for 0-arity case objects returns `productPrefix.hashCode` (the simple class name). This preserves the exact same hash values, avoiding any change in hash-dependent code paths. Other DataTypes did not need this change: - VarcharType, CharType, TimeType, GeometryType, GeographyType — already matched by type (case _: XType =>) across the codebase - StringType — has custom equals() comparing collationId - DecimalType, ArrayType, MapType, StructType — case classes with auto-generated equals() ### Why are the changes needed? Scala case object pattern matching (e.g., `case BinaryType =>`) relies on `equals()`, which for case objects defaults to reference equality. If a non-singleton instance of a DataType class is created at runtime — through any serialization framework that bypasses `readResolve()` — every case `BinaryType` => match in the codebase silently falls through, leading to errors like ([code pointer](https://github.com/apache/spark/blob/3e4df1c1c1e1d9f594a6afcf29b3bae05cc8a348/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/InterpretedUnsafeProjection.scala#L241)): ``` IllegalStateException: The data type 'binary' is not supported in generating a writer function... ``` Although the constructors are private, this is a compile-time guard only — serialization frameworks bypass constructors at runtime, so non-singleton instances can be created. ### Does this PR introduce _any_ user-facing change? Yes. Before this change, if a non-singleton DataType instance was created through deserialization, pattern matches like `case BinaryType =>` would silently fail, leading to non-deterministic runtime errors. After this change, non-singleton instances are correctly recognized as equal to the singleton, and pattern matching works as expected. ### How was this patch tested? 1. Unit test in DataTypeSuite (singleton DataType equality after deserialization): creates non-singleton instances via reflection for all 14 types, verifies bidirectional equality with singletons, matching hashCode, and correct PhysicalDataType resolution (no fallthrough to UninitializedPhysicalType). 2. Also verified that ExpressionSetSuite passes unchanged (its magic hashCode values are calibrated against IntegerType.hashCode, confirming hash preservation). ### Was this patch authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 4.6) Closes #54475 from timlee0119/spark-55681-datatype-equality. Authored-by: Tim Lee Signed-off-by: Wenchen Fan --- .../apache/spark/sql/types/BinaryType.scala | 4 ++ .../apache/spark/sql/types/BooleanType.scala | 4 ++ .../org/apache/spark/sql/types/ByteType.scala | 4 ++ .../sql/types/CalendarIntervalType.scala | 4 ++ .../org/apache/spark/sql/types/DateType.scala | 4 ++ .../apache/spark/sql/types/DoubleType.scala | 4 ++ .../apache/spark/sql/types/FloatType.scala | 4 ++ .../apache/spark/sql/types/IntegerType.scala | 4 ++ .../org/apache/spark/sql/types/LongType.scala | 4 ++ .../org/apache/spark/sql/types/NullType.scala | 4 ++ .../apache/spark/sql/types/ShortType.scala | 4 ++ .../spark/sql/types/TimestampNTZType.scala | 4 ++ .../spark/sql/types/TimestampType.scala | 4 ++ .../apache/spark/sql/types/VariantType.scala | 4 ++ .../spark/sql/types/DataTypeSuite.scala | 42 ++++++++++++++++++- 15 files changed, 97 insertions(+), 1 deletion(-) diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/BinaryType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/BinaryType.scala index 20bfd9bf5684f..7ece7902b9638 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/BinaryType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/BinaryType.scala @@ -31,6 +31,10 @@ class BinaryType private () extends AtomicType { */ override def defaultSize: Int = 100 + override def equals(obj: Any): Boolean = obj.isInstanceOf[BinaryType] + + override def hashCode(): Int = classOf[BinaryType].getSimpleName.hashCode + private[spark] override def asNullable: BinaryType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/BooleanType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/BooleanType.scala index 090c56eaf9af7..3427fd2dd3923 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/BooleanType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/BooleanType.scala @@ -32,6 +32,10 @@ class BooleanType private () extends AtomicType { */ override def defaultSize: Int = 1 + override def equals(obj: Any): Boolean = obj.isInstanceOf[BooleanType] + + override def hashCode(): Int = classOf[BooleanType].getSimpleName.hashCode + private[spark] override def asNullable: BooleanType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/ByteType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/ByteType.scala index 4a27a00dacb8a..924f6a320638b 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/ByteType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/ByteType.scala @@ -34,6 +34,10 @@ class ByteType private () extends IntegralType { override def simpleString: String = "tinyint" + override def equals(obj: Any): Boolean = obj.isInstanceOf[ByteType] + + override def hashCode(): Int = classOf[ByteType].getSimpleName.hashCode + private[spark] override def asNullable: ByteType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/CalendarIntervalType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/CalendarIntervalType.scala index f6b6256db0417..16deb461204a1 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/CalendarIntervalType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/CalendarIntervalType.scala @@ -39,6 +39,10 @@ class CalendarIntervalType private () extends DataType { override def typeName: String = "interval" + override def equals(obj: Any): Boolean = obj.isInstanceOf[CalendarIntervalType] + + override def hashCode(): Int = classOf[CalendarIntervalType].getSimpleName.hashCode + private[spark] override def asNullable: CalendarIntervalType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/DateType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/DateType.scala index 402c4c0d95298..f363d3423c170 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/DateType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/DateType.scala @@ -34,6 +34,10 @@ class DateType private () extends DatetimeType { */ override def defaultSize: Int = 4 + override def equals(obj: Any): Boolean = obj.isInstanceOf[DateType] + + override def hashCode(): Int = classOf[DateType].getSimpleName.hashCode + private[spark] override def asNullable: DateType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/DoubleType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/DoubleType.scala index 873f0c237c6c4..e0944f60d7496 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/DoubleType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/DoubleType.scala @@ -34,6 +34,10 @@ class DoubleType private () extends FractionalType { */ override def defaultSize: Int = 8 + override def equals(obj: Any): Boolean = obj.isInstanceOf[DoubleType] + + override def hashCode(): Int = classOf[DoubleType].getSimpleName.hashCode + private[spark] override def asNullable: DoubleType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/FloatType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/FloatType.scala index df4b03cd42bd4..9888ead910451 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/FloatType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/FloatType.scala @@ -34,6 +34,10 @@ class FloatType private () extends FractionalType { */ override def defaultSize: Int = 4 + override def equals(obj: Any): Boolean = obj.isInstanceOf[FloatType] + + override def hashCode(): Int = classOf[FloatType].getSimpleName.hashCode + private[spark] override def asNullable: FloatType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/IntegerType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/IntegerType.scala index dc4727cb1215b..33485b2267153 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/IntegerType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/IntegerType.scala @@ -34,6 +34,10 @@ class IntegerType private () extends IntegralType { override def simpleString: String = "int" + override def equals(obj: Any): Boolean = obj.isInstanceOf[IntegerType] + + override def hashCode(): Int = classOf[IntegerType].getSimpleName.hashCode + private[spark] override def asNullable: IntegerType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/LongType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/LongType.scala index f65c4c70acd27..56f45c25f65c4 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/LongType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/LongType.scala @@ -34,6 +34,10 @@ class LongType private () extends IntegralType { override def simpleString: String = "bigint" + override def equals(obj: Any): Boolean = obj.isInstanceOf[LongType] + + override def hashCode(): Int = classOf[LongType].getSimpleName.hashCode + private[spark] override def asNullable: LongType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/NullType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/NullType.scala index 4e7fd3a00a8af..d4cb0c2a95f98 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/NullType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/NullType.scala @@ -31,6 +31,10 @@ class NullType private () extends DataType { // Defined with a private constructor so the companion object is the only possible instantiation. override def defaultSize: Int = 1 + override def equals(obj: Any): Boolean = obj.isInstanceOf[NullType] + + override def hashCode(): Int = classOf[NullType].getSimpleName.hashCode + private[spark] override def asNullable: NullType = this override def typeName: String = "void" diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/ShortType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/ShortType.scala index c3b6bc75facd3..45cdf913707a8 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/ShortType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/ShortType.scala @@ -34,6 +34,10 @@ class ShortType private () extends IntegralType { override def simpleString: String = "smallint" + override def equals(obj: Any): Boolean = obj.isInstanceOf[ShortType] + + override def hashCode(): Int = classOf[ShortType].getSimpleName.hashCode + private[spark] override def asNullable: ShortType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/TimestampNTZType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/TimestampNTZType.scala index b08d16f0e2c97..a49e195fc24c0 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/TimestampNTZType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/TimestampNTZType.scala @@ -38,6 +38,10 @@ class TimestampNTZType private () extends DatetimeType { override def typeName: String = "timestamp_ntz" + override def equals(obj: Any): Boolean = obj.isInstanceOf[TimestampNTZType] + + override def hashCode(): Int = classOf[TimestampNTZType].getSimpleName.hashCode + private[spark] override def asNullable: TimestampNTZType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/TimestampType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/TimestampType.scala index bf869d1f38c57..7d6c683df3347 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/TimestampType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/TimestampType.scala @@ -35,6 +35,10 @@ class TimestampType private () extends DatetimeType { */ override def defaultSize: Int = 8 + override def equals(obj: Any): Boolean = obj.isInstanceOf[TimestampType] + + override def hashCode(): Int = classOf[TimestampType].getSimpleName.hashCode + private[spark] override def asNullable: TimestampType = this } diff --git a/sql/api/src/main/scala/org/apache/spark/sql/types/VariantType.scala b/sql/api/src/main/scala/org/apache/spark/sql/types/VariantType.scala index 4d775c3e1e390..808503c37c2e0 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/types/VariantType.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/types/VariantType.scala @@ -32,6 +32,10 @@ class VariantType private () extends AtomicType { // picked and we currently don't have any data to support it. This may need revisiting later. override def defaultSize: Int = 2048 + override def equals(obj: Any): Boolean = obj.isInstanceOf[VariantType] + + override def hashCode(): Int = classOf[VariantType].getSimpleName.hashCode + /** This is a no-op because values with VARIANT type are always nullable. */ private[spark] override def asNullable: VariantType = this } diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/types/DataTypeSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/types/DataTypeSuite.scala index c698a03d7f349..ce4f5e89be2b8 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/types/DataTypeSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/types/DataTypeSuite.scala @@ -23,7 +23,7 @@ import org.json4s.jackson.JsonMethods import org.apache.spark.{SparkException, SparkFunSuite, SparkIllegalArgumentException} import org.apache.spark.sql.catalyst.analysis.{caseInsensitiveResolution, caseSensitiveResolution} import org.apache.spark.sql.catalyst.parser.{CatalystSqlParser, ParseException} -import org.apache.spark.sql.catalyst.types.DataTypeUtils +import org.apache.spark.sql.catalyst.types.{DataTypeUtils, PhysicalDataType, UninitializedPhysicalType} import org.apache.spark.sql.catalyst.util.{CollationFactory, StringConcat} import org.apache.spark.sql.types.DataTypeTestUtils.{dayTimeIntervalTypes, yearMonthIntervalTypes} @@ -1447,4 +1447,44 @@ class DataTypeSuite extends SparkFunSuite { condition = "PARSE_SYNTAX_ERROR", parameters = Map("error" -> "'time'", "hint" -> "")) } + + test("singleton DataType equality after deserialization") { + // Singleton DataTypes that use `case object` pattern matching (e.g., `case BinaryType =>`). + // If a non-singleton instance is created (e.g., via Kryo deserialization which doesn't call + // readResolve), the pattern match would fail without proper equals/hashCode overrides. + val singletonTypes: Seq[(DataType, Class[_ <: DataType])] = Seq( + (BinaryType, classOf[BinaryType]), + (BooleanType, classOf[BooleanType]), + (ByteType, classOf[ByteType]), + (ShortType, classOf[ShortType]), + (IntegerType, classOf[IntegerType]), + (LongType, classOf[LongType]), + (FloatType, classOf[FloatType]), + (DoubleType, classOf[DoubleType]), + (DateType, classOf[DateType]), + (TimestampType, classOf[TimestampType]), + (TimestampNTZType, classOf[TimestampNTZType]), + (NullType, classOf[NullType]), + (CalendarIntervalType, classOf[CalendarIntervalType]), + (VariantType, classOf[VariantType]) + ) + + singletonTypes.foreach { case (singleton, clazz) => + val ctor = clazz.getDeclaredConstructor() + ctor.setAccessible(true) + val nonSingleton = ctor.newInstance() + assert(nonSingleton ne singleton, + s"${clazz.getSimpleName}: reflection should create a distinct instance") + + assert(nonSingleton == singleton, + s"${clazz.getSimpleName}: non-singleton == singleton should be true") + assert(singleton == nonSingleton, + s"${clazz.getSimpleName}: singleton == non-singleton should be true") + assert(nonSingleton.hashCode == singleton.hashCode, + s"${clazz.getSimpleName}: hashCode should be equal") + + assert(PhysicalDataType(nonSingleton) != UninitializedPhysicalType, + s"${clazz.getSimpleName}: PhysicalDataType should recognize non-singleton instance") + } + } } From cd01c4c6f6462dc558ed42473559be4011347afa Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Wed, 25 Feb 2026 22:18:56 +0800 Subject: [PATCH 031/130] [SPARK-55682][CORE][SQL] ServiceLoader returned iterator may throw `NoClassDefFoundError` on `hasNext()` ### What changes were proposed in this pull request? JDK 24 introduces a behavior change on `ServiceLoader`'s returned iterator, `iterator.hasNext()` might throw `NoClassDefFoundError`, which previously only happened on `iterator.next()`. See more details at OpenJDK bug report [JDK-8350481](https://bugs.openjdk.org/browse/JDK-8350481) Another issue is even the [Javadoc](https://docs.oracle.com/en/java/javase/25/docs/api//java.base/java/util/ServiceLoader.html#iterator()) of `ServiceLoader` say > Its hasNext and next methods can therefore throw a ServiceConfigurationError for any of the reasons specified > in the Errors section above. To write robust code it is only necessary to catch ServiceConfigurationError when > using the iterator. If an error is thrown then subsequent invocations of the iterator will make a best effort > to locate and instantiate the next available provider, but in general such recovery cannot be guaranteed. but it actually might throw `NoClassDefFoundError`. See more details at OpenJDK bug report [JDK-8196182](https://bugs.openjdk.org/browse/JDK-8196182) ### Why are the changes needed? Enable Java 25 support. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Changes in `HadoopDelegationTokenManager` are covered by UT, other 2 places are not, need to review carefully. ``` $ export JAVA_HOME=/path/of/openjdk-25 $ build/sbt -Phive "hive/testOnly *HiveHadoopDelegationTokenManagerSuite" ``` Before ``` [info] Cause: java.lang.ClassNotFoundException: org.apache.hadoop.hive.conf.HiveConf [info] at org.apache.spark.sql.hive.security.HiveHadoopDelegationTokenManagerSuite$$anon$1.loadClass(HiveHadoopDelegationTokenManagerSuite.scala:51) [info] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490) [info] at java.base/java.lang.Class.getDeclaredConstructors0(Native Method) [info] at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:2985) [info] at java.base/java.lang.Class.getConstructor0(Class.java:3180) [info] at java.base/java.lang.Class.getConstructor(Class.java:2199) [info] at java.base/java.util.ServiceLoader.getConstructor(ServiceLoader.java:623) [info] at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1111) [info] at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1142) [info] at java.base/java.util.ServiceLoader$1.hasNext(ServiceLoader.java:1164) [info] at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1246) [info] at org.apache.spark.deploy.security.HadoopDelegationTokenManager.loadProviders(HadoopDelegationTokenManager.scala:273) [info] at org.apache.spark.deploy.security.HadoopDelegationTokenManager.(HadoopDelegationTokenManager.scala:79) ... [info] Run completed in 1 second, 186 milliseconds. [info] Total number of tests run: 3 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 2, failed 1, canceled 0, ignored 0, pending 0 [info] *** 1 TEST FAILED *** [error] Failed tests: [error] org.apache.spark.sql.hive.security.HiveHadoopDelegationTokenManagerSuite [error] (hive / Test / testOnly) sbt.TestsFailedException: Tests unsuccessful [error] Total time: 192 s (0:03:12.0), completed Feb 25, 2026, 4:40:21 PM ``` After ``` [info] HiveHadoopDelegationTokenManagerSuite: [info] - default configuration (44 milliseconds) 16:41:38.695 WARN org.apache.spark.deploy.security.HadoopDelegationTokenManager: spark.yarn.security.credentials.hive.enabled is deprecated. Please use spark.security.credentials.hive.enabled instead. [info] - using deprecated configurations (6 milliseconds) [info] - SPARK-23209: obtain tokens when Hive classes are not available (284 milliseconds) [info] Run completed in 1 second, 200 milliseconds. [info] Total number of tests run: 3 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 3, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. [success] Total time: 33 s, completed Feb 25, 2026, 4:41:43 PM ``` A similar issue was fixed in Hadoop too, see HADOOP-19821. I created [a simple project](https://github.com/pan3793/HADOOP-19821) to help reviewers better understand this issue and solution. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54476 from pan3793/SPARK-55682. Authored-by: Cheng Pan Signed-off-by: Cheng Pan --- .../security/HadoopDelegationTokenManager.scala | 9 +++++++-- .../apache/spark/sql/classic/SparkSession.scala | 14 ++++++++++---- .../sql/execution/datasources/DataSource.scala | 8 ++++++++ .../jdbc/connection/ConnectionProvider.scala | 13 +++++++++---- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/core/src/main/scala/org/apache/spark/deploy/security/HadoopDelegationTokenManager.scala b/core/src/main/scala/org/apache/spark/deploy/security/HadoopDelegationTokenManager.scala index bc77159415473..58bbd7477bd07 100644 --- a/core/src/main/scala/org/apache/spark/deploy/security/HadoopDelegationTokenManager.scala +++ b/core/src/main/scala/org/apache/spark/deploy/security/HadoopDelegationTokenManager.scala @@ -270,9 +270,14 @@ private[spark] class HadoopDelegationTokenManager( val providers = mutable.ArrayBuffer[HadoopDelegationTokenProvider]() val iterator = loader.iterator - while (iterator.hasNext) { + var keepLoading = true + while (keepLoading) { try { - providers += iterator.next + if (iterator.hasNext) { + providers += iterator.next() + } else { + keepLoading = false + } } catch { case t: Throwable => logDebug(s"Failed to load built in provider.", t) diff --git a/sql/core/src/main/scala/org/apache/spark/sql/classic/SparkSession.scala b/sql/core/src/main/scala/org/apache/spark/sql/classic/SparkSession.scala index d1c7c406544c9..fef62d8b2755d 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/classic/SparkSession.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/classic/SparkSession.scala @@ -1281,12 +1281,18 @@ object SparkSession extends SparkSessionCompanion with Logging { Utils.getContextOrSparkClassLoader) val loadedExts = loader.iterator() - while (loadedExts.hasNext) { + var keepLoading = true + while (keepLoading) { try { - val ext = loadedExts.next() - ext(extensions) + if (loadedExts.hasNext) { + val ext = loadedExts.next() + ext(extensions) + } else { + keepLoading = false + } } catch { - case e: Throwable => logWarning("Failed to load session extension", e) + case e: Throwable => + logWarning("Failed to load session extension", e) } } } diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSource.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSource.scala index a48c71ad0d362..0c234e3fcf189 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSource.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSource.scala @@ -734,6 +734,14 @@ object DataSource extends Logging { } else { throw e } + case e: NoClassDefFoundError => + // NoClassDefFoundError's class name uses "/" rather than "." for packages + val className = e.getMessage.replaceAll("/", ".") + if (spark2RemovedClasses.contains(className)) { + throw QueryExecutionErrors.incompatibleDataSourceRegisterError(e) + } else { + throw e + } } } diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProvider.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProvider.scala index 7342f701e3455..03257140b8ee0 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProvider.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProvider.scala @@ -39,11 +39,16 @@ protected abstract class ConnectionProviderBase extends Logging { val providers = mutable.ArrayBuffer[JdbcConnectionProvider]() val iterator = loader.iterator - while (iterator.hasNext) { + var keepLoading = true + while (keepLoading) { try { - val provider = iterator.next - logDebug(s"Loaded built-in provider: $provider") - providers += provider + if (iterator.hasNext) { + val provider = iterator.next() + logDebug(s"Loaded built-in provider: $provider") + providers += provider + } else { + keepLoading = false + } } catch { case t: Throwable => logError("Failed to load built-in provider.") From e5a203c4a809025dbfc37d4ad7ac24bc4b9ecf68 Mon Sep 17 00:00:00 2001 From: Kousuke Saruta Date: Wed, 25 Feb 2026 22:20:10 +0800 Subject: [PATCH 032/130] [SPARK-55684][BUILD] Upgrade sbt to `1.12.4` ### What changes were proposed in this pull request? This PR proposes to upgrade sbt to `1.12.4`. ### Why are the changes needed? Release note: https://github.com/sbt/sbt/releases/tag/v1.12.4 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? GA. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54480 from sarutak/upgrade-sbt-1.12.4. Authored-by: Kousuke Saruta Signed-off-by: Cheng Pan --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index cd1a9cf355fff..8302cc986b157 100644 --- a/project/build.properties +++ b/project/build.properties @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -sbt.version=1.12.3 +sbt.version=1.12.4 From 8bd7b6e1cf000d57d910dfd326de980f48bcbe85 Mon Sep 17 00:00:00 2001 From: Anastasiia Terenteva Date: Wed, 25 Feb 2026 10:25:06 -0400 Subject: [PATCH 033/130] [SPARK-55606][CONNECT] Server-side implementation of GetStatus API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? Server-side implementation of the GetStatus API: - Introduce a variable in ExecuteEventsManager to track execution termination reason after it's closed. - Track minimal execution termination information in SessionHolder's inactiveOperations cache. - Use SessionHolder's activeOperations and inactiveOperations lists for determining execution status in GetStatus API handler. - Add plugin interface for GetStatus operation for processing custom proto extensions. ### Why are the changes needed? GetStatus API allows to monitor status of executions in a session, which is particularly useful in multithreaded clients. ### Does this PR introduce _any_ user-facing change? Yes. It's a new Spark Connect API. ### How was this patch tested? - New tests were added. - E2E tests with checking for real (not mocked) execution lifecycles are coming in client-side PR. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: Claude 4.6 Opus High Closes #54445 from terana/get-status-server. Authored-by: Anastasiia Terenteva Signed-off-by: Herman van Hövell --- .../sql/connect/plugin/GetStatusPlugin.java | 77 ++++ .../spark/sql/connect/config/Connect.scala | 12 + .../plugin/SparkConnectPluginRegistry.scala | 46 ++- .../service/ExecuteEventsManager.scala | 79 +++- .../sql/connect/service/ExecuteHolder.scala | 21 ++ .../sql/connect/service/SessionHolder.scala | 60 ++- .../SparkConnectExecutionManager.scala | 4 +- .../SparkConnectGetStatusHandler.scala | 218 +++++++++++ .../connect/service/SparkConnectService.scala | 13 + .../sql/connect/SparkConnectTestUtils.scala | 28 +- .../SparkConnectPluginRegistrySuite.scala | 54 +++ .../service/ExecuteEventsManagerSuite.scala | 58 +++ .../service/GetStatusHandlerSuite.scala | 354 ++++++++++++++++++ .../SparkConnectExecutionManagerSuite.scala | 118 ++++++ .../SparkConnectSessionHolderSuite.scala | 88 +++++ 15 files changed, 1211 insertions(+), 19 deletions(-) create mode 100644 sql/connect/server/src/main/java/org/apache/spark/sql/connect/plugin/GetStatusPlugin.java create mode 100644 sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectGetStatusHandler.scala create mode 100644 sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/GetStatusHandlerSuite.scala create mode 100644 sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/SparkConnectExecutionManagerSuite.scala diff --git a/sql/connect/server/src/main/java/org/apache/spark/sql/connect/plugin/GetStatusPlugin.java b/sql/connect/server/src/main/java/org/apache/spark/sql/connect/plugin/GetStatusPlugin.java new file mode 100644 index 0000000000000..77a519099bf76 --- /dev/null +++ b/sql/connect/server/src/main/java/org/apache/spark/sql/connect/plugin/GetStatusPlugin.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.spark.sql.connect.plugin; + +import com.google.protobuf.Any; + +import java.util.List; +import java.util.Optional; + +import org.apache.spark.sql.connect.service.SessionHolder; + +/** + * Plugin interface for extending GetStatus RPC behavior in Spark Connect. + * + *

Classes implementing this interface must be trivially constructable (have a no-argument + * constructor) and should not rely on internal state. The plugin is invoked during GetStatus + * request handling, allowing custom logic to be executed based on request extensions. + * + *

The GetStatus RPC message has two extension points: + *

    + *
  • {@code GetStatusRequest.extensions} - request-level extensions
  • + *
  • {@code GetStatusRequest.OperationStatusRequest.extensions} + * - operation-level extensions
  • + *
+ * + *

And corresponding response extension points: + *

    + *
  • {@code GetStatusResponse.extensions} - response-level extensions
  • + *
  • {@code GetStatusResponse.OperationStatus.extensions} - operation-level extensions
  • + *
+ */ +public interface GetStatusPlugin { + + /** + * Process request-level extensions from a GetStatus request. + * + *

This method is called once per GetStatus request, before operation statuses are processed. + * Plugins can use the request extensions to customize behavior and return response extensions. + * + * @param sessionHolder the session holder for the current session + * @param requestExtensions the extensions from the GetStatus request + * @return optional list of response extensions to add to the GetStatusResponse; + * return {@code Optional.empty()} if this plugin does not handle the request extensions + */ + Optional> processRequestExtensions( + SessionHolder sessionHolder, List requestExtensions); + + /** + * Process operation-level extensions from an OperationStatusRequest. + * + *

This method is called once per operation whose status is requested. + * Plugins can use the operation-level extensions to customize per-operation behavior. + * + * @param operationId the operation ID being queried + * @param sessionHolder the session holder for the current session + * @param operationExtensions the extensions from the OperationStatusRequest + * @return optional list of response extensions to add to the OperationStatus; + * return {@code Optional.empty()} if this plugin does not handle the extensions + */ + Optional> processOperationExtensions( + String operationId, SessionHolder sessionHolder, List operationExtensions); +} diff --git a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/config/Connect.scala b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/config/Connect.scala index 1df97d855678e..e2d496239d290 100644 --- a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/config/Connect.scala +++ b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/config/Connect.scala @@ -218,6 +218,18 @@ object Connect { .toSequence .createWithDefault(Nil) + val CONNECT_EXTENSIONS_GET_STATUS_CLASSES = + buildStaticConf("spark.connect.extensions.getStatus.classes") + .doc(""" + |Comma separated list of classes that implement the trait + |org.apache.spark.sql.connect.plugin.GetStatusPlugin to support custom + |GetStatus extensions in proto. + |""".stripMargin) + .version("4.1.0") + .stringConf + .toSequence + .createWithDefault(Nil) + val CONNECT_ML_BACKEND_CLASSES = buildConf("spark.connect.ml.backend.classes") .doc(""" diff --git a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/plugin/SparkConnectPluginRegistry.scala b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/plugin/SparkConnectPluginRegistry.scala index fc4e7aed7aed5..b26b8fb43fbed 100644 --- a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/plugin/SparkConnectPluginRegistry.scala +++ b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/plugin/SparkConnectPluginRegistry.scala @@ -25,8 +25,8 @@ import org.apache.spark.sql.internal.SQLConf import org.apache.spark.util.Utils /** - * This object provides a global list of configured relation, expression and command plugins for - * Spark Connect. The plugins are used to handle custom message types. + * This object provides a global list of configured relation, expression, command, and getStatus + * plugins for Spark Connect. The plugins are used to handle custom message types. */ object SparkConnectPluginRegistry { @@ -46,15 +46,22 @@ object SparkConnectPluginRegistry { // expression[DummyExpressionPlugin](classOf[DummyExpressionPlugin]) ) + private lazy val getStatusPluginChain: Seq[getStatusPluginBuilder] = Seq( + // Adding a new plugin at compile time works like the example below: + // getStatus[DummyGetStatusPlugin](classOf[DummyGetStatusPlugin]) + ) + private var initialized = false private var relationRegistryCache: Seq[RelationPlugin] = Seq.empty private var expressionRegistryCache: Seq[ExpressionPlugin] = Seq.empty private var commandRegistryCache: Seq[CommandPlugin] = Seq.empty + private var getStatusRegistryCache: Seq[GetStatusPlugin] = Seq.empty // Type used to identify the closure responsible to instantiate a ServerInterceptor. type relationPluginBuilder = () => RelationPlugin type expressionPluginBuilder = () => ExpressionPlugin type commandPluginBuilder = () => CommandPlugin + type getStatusPluginBuilder = () => GetStatusPlugin def relationRegistry: Seq[RelationPlugin] = withInitialize { relationRegistryCache @@ -65,6 +72,9 @@ object SparkConnectPluginRegistry { def commandRegistry: Seq[CommandPlugin] = withInitialize { commandRegistryCache } + def getStatusRegistry: Seq[GetStatusPlugin] = withInitialize { + getStatusRegistryCache + } def mlBackendRegistry(conf: SQLConf): Seq[MLBackendPlugin] = loadMlBackendPlugins(conf) private def withInitialize[T](f: => Seq[T]): Seq[T] = { @@ -73,6 +83,7 @@ object SparkConnectPluginRegistry { relationRegistryCache = loadRelationPlugins() expressionRegistryCache = loadExpressionPlugins() commandRegistryCache = loadCommandPlugins() + getStatusRegistryCache = loadGetStatusPlugins() initialized = true } } @@ -88,6 +99,23 @@ object SparkConnectPluginRegistry { } } + /** + * Only visible for testing. Allows injecting test GetStatus plugins directly into the registry + * cache, bypassing the normal plugin chain loading. Forces initialization of all other caches + * if not already initialized, then overrides the GetStatus cache. + */ + private[connect] def setGetStatusPluginsForTesting(plugins: Seq[GetStatusPlugin]): Unit = { + synchronized { + if (!initialized) { + relationRegistryCache = loadRelationPlugins() + expressionRegistryCache = loadExpressionPlugins() + commandRegistryCache = loadCommandPlugins() + initialized = true + } + getStatusRegistryCache = plugins + } + } + /** * Only visible for testing */ @@ -109,6 +137,12 @@ object SparkConnectPluginRegistry { SparkEnv.get.conf.get(Connect.CONNECT_EXTENSIONS_COMMAND_CLASSES)) } + private[connect] def loadGetStatusPlugins(): Seq[GetStatusPlugin] = { + getStatusPluginChain.map(x => x()) ++ + createConfiguredPlugins( + SparkEnv.get.conf.get(Connect.CONNECT_EXTENSIONS_GET_STATUS_CLASSES)) + } + private[connect] def loadMlBackendPlugins(sqlConf: SQLConf): Seq[MLBackendPlugin] = { createConfiguredPlugins(sqlConf.getConf(Connect.CONNECT_ML_BACKEND_CLASSES)) } @@ -182,4 +216,12 @@ object SparkConnectPluginRegistry { */ def command[T <: CommandPlugin](cls: Class[T]): commandPluginBuilder = () => createInstance[CommandPlugin, T](cls) + + /** + * Creates a callable expression that instantiates the configured GetStatus plugin. + * + * Visible for testing only. + */ + def getStatus[T <: GetStatusPlugin](cls: Class[T]): getStatusPluginBuilder = + () => createInstance[GetStatusPlugin, T](cls) } diff --git a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/ExecuteEventsManager.scala b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/ExecuteEventsManager.scala index 61cd95621d156..351be8875ba1c 100644 --- a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/ExecuteEventsManager.scala +++ b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/ExecuteEventsManager.scala @@ -47,7 +47,55 @@ object ExecuteStatus { } /** - * Post request Connect events to @link org.apache.spark.scheduler.LiveListenerBus. + * Records why an operation terminated so that the reason remains available after the operation + * transitions to the closed state. + */ +sealed abstract class TerminationReason(val value: Int) + +object TerminationReason { + case object Succeeded extends TerminationReason(0) + case object Failed extends TerminationReason(1) + case object Canceled extends TerminationReason(2) +} + +/** + * Manage the lifecycle of an operation by tracking its status and termination reason. Post + * request Connect events to @link org.apache.spark.scheduler.LiveListenerBus and serve as an + * information source for GetStatus RPC. + * + * {{{ + * +---------------------------------------------+ + * | ExecuteEventsManager | + * | | + * | - Tracks operation lifecycle state | + * | - Posts events to event bus | + * | - Maintains termination info in memory | + * +---------------------------------------------+ + * | + * +-----------+-----------+ + * | | + * v v + * +------------------+ +------------------+ + * | GetStatus RPC | | Query History | + * | (Direct API) | | (Audit Log) | + * +------------------+ +------------------+ + * + * State Mapping Matrix: + * + * ExecuteStatus -> GetStatus API -> Query History + * + TerminationReason + * ---------------------------------------------------------------- + * Pending -> RUNNING -> (no event posted) + * Started -> RUNNING -> STARTED + * Analyzed -> RUNNING -> COMPILED + * ReadyForExecution -> RUNNING -> READY + * Finished -> TERMINATING -> FINISHED + * Failed -> TERMINATING -> FAILED + * Canceled -> TERMINATING -> CANCELED + * Closed+Succeeded -> SUCCEEDED -> CLOSED + * Closed+Failed -> FAILED -> CLOSED + * Closed+Canceled -> CANCELLED -> CLOSED + * }}} * * @param executeHolder: * Request for which the events are generated. @@ -70,7 +118,7 @@ case class ExecuteEventsManager(executeHolder: ExecuteHolder, clock: Clock) { private def sessionStatus = sessionHolder.eventManager.status - private var _status: ExecuteStatus = ExecuteStatus.Pending + @volatile private var _status: ExecuteStatus = ExecuteStatus.Pending private var error = Option.empty[Boolean] @@ -78,12 +126,36 @@ case class ExecuteEventsManager(executeHolder: ExecuteHolder, clock: Clock) { private var producedRowCount = Option.empty[Long] + @volatile private var _terminationReason: Option[TerminationReason] = None + /** * @return * Last event posted by the Connect request */ private[connect] def status: ExecuteStatus = _status + /** + * @return + * The reason for termination, set when the operation finishes, fails, or is canceled. Since + * the closed state itself does not convey why the operation ended, this value preserves that + * information for later use. + */ + private[connect] def terminationReason: Option[TerminationReason] = _terminationReason + + /** + * Updates the termination reason only if the new reason has a higher value than the current + * one. This established the ordering Canceled > Failed > Succeeded, which is consistent with + * ExecuteStatus ordering. This handles the cases when execution is interrupted or fails during + * cleanup. + */ + private def updateTerminationReason(newReason: TerminationReason): Unit = { + _terminationReason match { + case Some(currentReason) if currentReason.value >= newReason.value => + case _ => + _terminationReason = Some(newReason) + } + } + /** * @return * True when the Connect request has posted @link @@ -184,6 +256,7 @@ case class ExecuteEventsManager(executeHolder: ExecuteHolder, clock: Clock) { ExecuteStatus.Failed), ExecuteStatus.Canceled) canceled = Some(true) + updateTerminationReason(TerminationReason.Canceled) listenerBus .post(SparkListenerConnectOperationCanceled(jobTag, operationId, clock.getTimeMillis())) } @@ -203,6 +276,7 @@ case class ExecuteEventsManager(executeHolder: ExecuteHolder, clock: Clock) { ExecuteStatus.Finished), ExecuteStatus.Failed) error = Some(true) + updateTerminationReason(TerminationReason.Failed) listenerBus.post( SparkListenerConnectOperationFailed( jobTag, @@ -224,6 +298,7 @@ case class ExecuteEventsManager(executeHolder: ExecuteHolder, clock: Clock) { List(ExecuteStatus.Started, ExecuteStatus.ReadyForExecution), ExecuteStatus.Finished) producedRowCount = producedRowsCountOpt + updateTerminationReason(TerminationReason.Succeeded) listenerBus .post( diff --git a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/ExecuteHolder.scala b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/ExecuteHolder.scala index 42574b1f8d437..7f5670f439601 100644 --- a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/ExecuteHolder.scala +++ b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/ExecuteHolder.scala @@ -308,6 +308,8 @@ private[connect] class ExecuteHolder( responseObserver.removeAll() // Post "closed" to UI. eventsManager.postClosed() + // Update the termination info in the session holder after closure. + sessionHolder.closeOperation(this) } } @@ -331,6 +333,7 @@ private[connect] class ExecuteHolder( sparkSessionTags = sparkSessionTags, reattachable = reattachable, status = eventsManager.status, + terminationReason = eventsManager.terminationReason, creationTimeNs = creationTimeNs, lastAttachedRpcTimeNs = lastAttachedRpcTimeNs, closedTimeNs = closedTimeNs) @@ -341,6 +344,15 @@ private[connect] class ExecuteHolder( /** Get the operation ID. */ def operationId: String = key.operationId + + def getTerminationInfo: TerminationInfo = { + TerminationInfo( + userId = sessionHolder.userId, + sessionId = sessionHolder.sessionId, + operationId = executeKey.operationId, + status = eventsManager.status, + terminationReason = eventsManager.terminationReason) + } } private object ExecuteHolder { @@ -406,9 +418,18 @@ case class ExecuteInfo( sparkSessionTags: Set[String], reattachable: Boolean, status: ExecuteStatus, + terminationReason: Option[TerminationReason], creationTimeNs: Long, lastAttachedRpcTimeNs: Option[Long], closedTimeNs: Option[Long]) { def key: ExecuteKey = ExecuteKey(userId, sessionId, operationId) } + +/** Minimal termination status information for inactive operations. */ +case class TerminationInfo( + userId: String, + sessionId: String, + operationId: String, + status: ExecuteStatus, + terminationReason: Option[TerminationReason]) diff --git a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SessionHolder.scala b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SessionHolder.scala index d0d0f0ba750a3..912543ac13ddd 100644 --- a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SessionHolder.scala +++ b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SessionHolder.scala @@ -96,16 +96,15 @@ case class SessionHolder(userId: String, sessionId: String, session: SparkSessio // Set of active operation IDs for this session. private val activeOperationIds: mutable.Set[String] = mutable.Set.empty - // Cache of inactive operation IDs for this session, either completed, interrupted or abandoned. - // The Boolean is just a placeholder since Guava needs a pair. - private lazy val inactiveOperationIds: Cache[String, Boolean] = + // Cache of inactive operations for this session, either completed, interrupted or abandoned. + private lazy val inactiveOperations: Cache[String, TerminationInfo] = CacheBuilder .newBuilder() .ticker(Ticker.systemTicker()) .expireAfterAccess( SparkEnv.get.conf.get(Connect.CONNECT_INACTIVE_OPERATIONS_CACHE_EXPIRATION_MINS), TimeUnit.MINUTES) - .build[String, Boolean]() + .build[String, TerminationInfo]() // The cache that maps an error id to a throwable. The throwable in cache is independent to // each other. @@ -197,7 +196,7 @@ case class SessionHolder(userId: String, sessionId: String, session: SparkSessio if (activeOperationIds.contains(operationId)) { return Some(true) } - Option(inactiveOperationIds.getIfPresent(operationId)) match { + Option(inactiveOperations.getIfPresent(operationId)) match { case Some(_) => return Some(false) case None => @@ -206,13 +205,50 @@ case class SessionHolder(userId: String, sessionId: String, session: SparkSessio } /** - * Close an operation in this session by removing its operation ID. + * Returns the TerminationInfo for an inactive operation if it exists in the cache. Cache + * expiration is configured with CONNECT_INACTIVE_OPERATIONS_CACHE_EXPIRATION_MINS. * - * Called only by SparkConnectExecutionManager when an execution is ended. + * @param operationId + * @return + * Some(TerminationInfo) if the operation was closed recently, None if no inactive operation + * with this id is found. + */ + private[service] def getInactiveOperationInfo(operationId: String): Option[TerminationInfo] = { + Option(inactiveOperations.getIfPresent(operationId)) + } + + /** + * Returns all inactive operations for this session. These are operations that were closed and + * are still in the cache. Cache expiration is configured with + * CONNECT_INACTIVE_OPERATIONS_CACHE_EXPIRATION_MINS. + * + * @return + * Sequence of TerminationInfo for inactive operations. + */ + private[service] def listInactiveOperations(): Seq[TerminationInfo] = { + inactiveOperations.asMap().values().asScala.toSeq + } + + /** + * Returns all active operation IDs for this session. + * + * @return + * Sequence of operation IDs that are currently active. + */ + private[service] def listActiveOperationIds(): Seq[String] = { + activeOperationIds.synchronized { + activeOperationIds.toSeq + } + } + + /** + * Close an operation in this session by storing its TerminationInfo and removing from active + * set. */ - private[service] def closeOperation(operationId: String): Unit = { - inactiveOperationIds.put(operationId, true) - activeOperationIds.remove(operationId) + private[service] def closeOperation(executeHolder: ExecuteHolder): Unit = { + val terminationInfo = executeHolder.getTerminationInfo + inactiveOperations.put(terminationInfo.operationId, terminationInfo) + activeOperationIds.remove(terminationInfo.operationId) } /** @@ -249,7 +285,7 @@ case class SessionHolder(userId: String, sessionId: String, session: SparkSessio SparkConnectService.executionManager.getExecuteHolder(executeKey).foreach { executeHolder => if (executeHolder.sparkSessionTags.contains(tag)) { if (executeHolder.interrupt()) { - closeOperation(operationId) + closeOperation(executeHolder) interruptedIds += operationId } } @@ -268,7 +304,7 @@ case class SessionHolder(userId: String, sessionId: String, session: SparkSessio val executeKey = ExecuteKey(userId, sessionId, operationId) SparkConnectService.executionManager.getExecuteHolder(executeKey).foreach { executeHolder => if (executeHolder.interrupt()) { - closeOperation(operationId) + closeOperation(executeHolder) interruptedIds += operationId } } diff --git a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectExecutionManager.scala b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectExecutionManager.scala index 5f01676d9f898..768c6a8581880 100644 --- a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectExecutionManager.scala +++ b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectExecutionManager.scala @@ -157,12 +157,12 @@ private[connect] class SparkConnectExecutionManager() extends Logging { // getting an INVALID_HANDLE.OPERATION_ABANDONED error on a retry. if (abandoned) { abandonedTombstones.put(key, executeHolder.getExecuteInfo) - executeHolder.sessionHolder.closeOperation(executeHolder.operationId) + executeHolder.sessionHolder.closeOperation(executeHolder) } // Remove the execution from the map *after* putting it in abandonedTombstones. executions.remove(key) - executeHolder.sessionHolder.closeOperation(executeHolder.operationId) + executeHolder.sessionHolder.closeOperation(executeHolder) updateLastExecutionTime() diff --git a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectGetStatusHandler.scala b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectGetStatusHandler.scala new file mode 100644 index 0000000000000..c37061ff2ebae --- /dev/null +++ b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectGetStatusHandler.scala @@ -0,0 +1,218 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.spark.sql.connect.service + +import scala.jdk.CollectionConverters._ +import scala.jdk.OptionConverters._ +import scala.util.control.NonFatal + +import io.grpc.stub.StreamObserver + +import org.apache.spark.connect.proto +import org.apache.spark.internal.{Logging, LogKeys} +import org.apache.spark.sql.connect.plugin.SparkConnectPluginRegistry + +class SparkConnectGetStatusHandler(responseObserver: StreamObserver[proto.GetStatusResponse]) + extends Logging { + + def handle(request: proto.GetStatusRequest): Unit = { + val previousSessionId = request.hasClientObservedServerSideSessionId match { + case true => Some(request.getClientObservedServerSideSessionId) + case false => None + } + val sessionHolder = SparkConnectService.sessionManager.getIsolatedSession( + SessionKey(request.getUserContext.getUserId, request.getSessionId), + previousSessionId) + + val responseBuilder = proto.GetStatusResponse + .newBuilder() + .setSessionId(request.getSessionId) + .setServerSideSessionId(sessionHolder.serverSessionId) + + val responseExtensions = + processRequestExtensionsViaPlugins(sessionHolder, request.getExtensionsList) + responseExtensions.foreach(responseBuilder.addExtensions) + + if (request.hasOperationStatus) { + val operationStatusRequest = request.getOperationStatus + val requestedOperationIds = + operationStatusRequest.getOperationIdsList.asScala.distinct.toSeq + val operationExtensions = operationStatusRequest.getExtensionsList + + val operationStatuses = if (requestedOperationIds.isEmpty) { + // If no specific operation IDs are requested, + // return status of all known operations in session + getAllOperationStatuses(sessionHolder, operationExtensions) + } else { + // Return status only for the requested operation IDs + requestedOperationIds.map { operationId => + getOperationStatus(sessionHolder, operationId, operationExtensions) + } + } + + operationStatuses.foreach(responseBuilder.addOperationStatuses) + } + + responseObserver.onNext(responseBuilder.build()) + responseObserver.onCompleted() + } + + private def getOperationStatus( + sessionHolder: SessionHolder, + operationId: String, + operationExtensions: java.util.List[com.google.protobuf.Any]) + : proto.GetStatusResponse.OperationStatus = { + val executeKey = ExecuteKey(sessionHolder.userId, sessionHolder.sessionId, operationId) + + // First look up operation in active list, then in inactive. This ordering handles the case + // where a concurrent thread moves the operation to inactive, and we don't find it neither in + // active list, nor in inactive. + val activeState: Option[proto.GetStatusResponse.OperationStatus.OperationState] = + SparkConnectService.executionManager + .getExecuteHolder(executeKey) + .map { executeHolder => + val info = executeHolder.getExecuteInfo + mapStatusToState(info.operationId, info.status, info.terminationReason) + } + + // Check inactiveOperations - this status prevails over activeState. + val state = sessionHolder + .getInactiveOperationInfo(operationId) + .map { info => + mapStatusToState(info.operationId, info.status, info.terminationReason) + } + .orElse(activeState) + .getOrElse(proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_UNKNOWN) + + val responseExtensions = + processOperationExtensionsViaPlugins(sessionHolder, operationExtensions, operationId) + + buildOperationStatus(operationId, state, responseExtensions) + } + + private def getAllOperationStatuses( + sessionHolder: SessionHolder, + operationExtensions: java.util.List[com.google.protobuf.Any]) + : Seq[proto.GetStatusResponse.OperationStatus] = { + val allOperationIds = + (sessionHolder.listActiveOperationIds() ++ + sessionHolder.listInactiveOperations().map(_.operationId)).distinct + + allOperationIds.map { operationId => + getOperationStatus(sessionHolder, operationId, operationExtensions) + } + } + + private def mapStatusToState( + operationId: String, + status: ExecuteStatus, + terminationReason: Option[TerminationReason]) + : proto.GetStatusResponse.OperationStatus.OperationState = { + status match { + case ExecuteStatus.Pending | ExecuteStatus.Started | ExecuteStatus.Analyzed | + ExecuteStatus.ReadyForExecution => + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_RUNNING + + // Finished, Failed, Canceled are terminating states - resources haven't been cleaned yet + case ExecuteStatus.Finished | ExecuteStatus.Failed | ExecuteStatus.Canceled => + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_TERMINATING + + case ExecuteStatus.Closed => + if (terminationReason.isEmpty) { + // This should not happen: ExecuteEventsManager processes state transitions + // from a single thread at a time, so there are no concurrent changes and + // terminationReason should always be set before reaching Closed. + logError( + log"Operation ${MDC(LogKeys.OPERATION_ID, operationId)} is Closed but " + + log"terminationReason is not set. status=${MDC(LogKeys.STATUS, status)}") + } + mapTerminationReasonToState(terminationReason) + } + } + + private def mapTerminationReasonToState(terminationReason: Option[TerminationReason]) + : proto.GetStatusResponse.OperationStatus.OperationState = { + terminationReason match { + case Some(TerminationReason.Succeeded) => + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_SUCCEEDED + case Some(TerminationReason.Failed) => + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_FAILED + case Some(TerminationReason.Canceled) => + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_CANCELLED + case None => + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_UNKNOWN + } + } + + private def buildOperationStatus( + operationId: String, + state: proto.GetStatusResponse.OperationStatus.OperationState, + extensions: Seq[com.google.protobuf.Any] = Seq.empty) + : proto.GetStatusResponse.OperationStatus = { + val builder = proto.GetStatusResponse.OperationStatus + .newBuilder() + .setOperationId(operationId) + .setState(state) + extensions.foreach(builder.addExtensions) + builder.build() + } + + private def processRequestExtensionsViaPlugins( + sessionHolder: SessionHolder, + requestExtensions: java.util.List[com.google.protobuf.Any]) + : Seq[com.google.protobuf.Any] = { + SparkConnectPluginRegistry.getStatusRegistry.flatMap { plugin => + try { + plugin.processRequestExtensions(sessionHolder, requestExtensions).toScala match { + case Some(extensions) => extensions.asScala.toSeq + case None => Seq.empty + } + } catch { + case NonFatal(e) => + logWarning( + log"Plugin ${MDC(LogKeys.CLASS_NAME, plugin.getClass.getName)} failed to process " + + log"request extensions", + e) + Seq.empty + } + } + } + + private def processOperationExtensionsViaPlugins( + sessionHolder: SessionHolder, + operationExtensions: java.util.List[com.google.protobuf.Any], + operationId: String): Seq[com.google.protobuf.Any] = { + SparkConnectPluginRegistry.getStatusRegistry.flatMap { plugin => + try { + plugin + .processOperationExtensions(operationId, sessionHolder, operationExtensions) + .toScala match { + case Some(extensions) => extensions.asScala.toSeq + case None => Seq.empty + } + } catch { + case NonFatal(e) => + logWarning( + log"Plugin ${MDC(LogKeys.CLASS_NAME, plugin.getClass.getName)} failed to process " + + log"operation extensions for operation ${MDC(LogKeys.OPERATION_ID, operationId)}", + e) + Seq.empty + } + } + } +} diff --git a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectService.scala b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectService.scala index 00b93c19b2c73..c14c21bd6ccb3 100644 --- a/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectService.scala +++ b/sql/connect/server/src/main/scala/org/apache/spark/sql/connect/service/SparkConnectService.scala @@ -246,6 +246,19 @@ class SparkConnectService(debug: Boolean) extends AsyncService with BindableServ } } + override def getStatus( + request: proto.GetStatusRequest, + responseObserver: StreamObserver[proto.GetStatusResponse]): Unit = { + try { + new SparkConnectGetStatusHandler(responseObserver).handle(request) + } catch + ErrorUtils.handleError( + "getStatus", + observer = responseObserver, + userId = request.getUserContext.getUserId, + sessionId = request.getSessionId) + } + private def methodWithCustomMarshallers( methodDesc: MethodDescriptor[Message, Message]): MethodDescriptor[Message, Message] = { val recursionLimit = diff --git a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/SparkConnectTestUtils.scala b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/SparkConnectTestUtils.scala index d06c93cc1cad6..d6a6390600da4 100644 --- a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/SparkConnectTestUtils.scala +++ b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/SparkConnectTestUtils.scala @@ -18,8 +18,9 @@ package org.apache.spark.sql.connect import java.util.UUID +import org.apache.spark.connect.proto import org.apache.spark.sql.classic.SparkSession -import org.apache.spark.sql.connect.service.{SessionHolder, SparkConnectService} +import org.apache.spark.sql.connect.service.{ExecuteHolder, ExecuteStatus, SessionHolder, SessionStatus, SparkConnectService} object SparkConnectTestUtils { @@ -33,4 +34,29 @@ object SparkConnectTestUtils { SparkConnectService.sessionManager.putSessionForTesting(ret) ret } + + /** Creates a dummy execute holder for use in tests. */ + def createDummyExecuteHolder( + sessionHolder: SessionHolder, + command: proto.Command): ExecuteHolder = { + sessionHolder.eventManager.status_(SessionStatus.Started) + val request = proto.ExecutePlanRequest + .newBuilder() + .setPlan( + proto.Plan + .newBuilder() + .setCommand(command) + .build()) + .setSessionId(sessionHolder.sessionId) + .setUserContext( + proto.UserContext + .newBuilder() + .setUserId(sessionHolder.userId) + .build()) + .build() + val executeHolder = + SparkConnectService.executionManager.createExecuteHolder(request) + executeHolder.eventsManager.status_(ExecuteStatus.Started) + executeHolder + } } diff --git a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/plugin/SparkConnectPluginRegistrySuite.scala b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/plugin/SparkConnectPluginRegistrySuite.scala index 32dbc9595eab2..4617a86842248 100644 --- a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/plugin/SparkConnectPluginRegistrySuite.scala +++ b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/plugin/SparkConnectPluginRegistrySuite.scala @@ -31,6 +31,7 @@ import org.apache.spark.sql.connect.ConnectProtoUtils import org.apache.spark.sql.connect.common.InvalidPlanInput import org.apache.spark.sql.connect.config.Connect import org.apache.spark.sql.connect.planner.{SparkConnectPlanner, SparkConnectPlanTest} +import org.apache.spark.sql.connect.service.SessionHolder import org.apache.spark.sql.test.SharedSparkSession class DummyPlugin extends RelationPlugin { @@ -45,6 +46,19 @@ class DummyExpressionPlugin extends ExpressionPlugin { planner: SparkConnectPlanner): Optional[Expression] = Optional.empty() } +class DummyGetStatusPlugin extends GetStatusPlugin { + override def processRequestExtensions( + sessionHolder: SessionHolder, + requestExtensions: java.util.List[protobuf.Any]): Optional[java.util.List[protobuf.Any]] = + Optional.empty() + + override def processOperationExtensions( + operationId: String, + sessionHolder: SessionHolder, + operationExtensions: java.util.List[protobuf.Any]): Optional[java.util.List[protobuf.Any]] = + Optional.empty() +} + class DummyPluginNoTrivialCtor(id: Int) extends RelationPlugin { override def transform( relation: Array[Byte], @@ -117,6 +131,9 @@ class SparkConnectPluginRegistrySuite extends SharedSparkSession with SparkConne if (SparkEnv.get.conf.contains(Connect.CONNECT_EXTENSIONS_COMMAND_CLASSES)) { SparkEnv.get.conf.remove(Connect.CONNECT_EXTENSIONS_COMMAND_CLASSES) } + if (SparkEnv.get.conf.contains(Connect.CONNECT_EXTENSIONS_GET_STATUS_CLASSES)) { + SparkEnv.get.conf.remove(Connect.CONNECT_EXTENSIONS_GET_STATUS_CLASSES) + } SparkConnectPluginRegistry.reset() } @@ -239,6 +256,31 @@ class SparkConnectPluginRegistrySuite extends SharedSparkSession with SparkConne assert(SparkConnectPluginRegistry.loadCommandPlugins().isEmpty) } + test("GetStatus registry is empty by default") { + assert(SparkConnectPluginRegistry.loadGetStatusPlugins().isEmpty) + } + + test("GetStatus plugin loaded dynamically from config") { + withSparkConf( + Connect.CONNECT_EXTENSIONS_GET_STATUS_CLASSES.key -> + "org.apache.spark.sql.connect.plugin.DummyGetStatusPlugin") { + val plugins = SparkConnectPluginRegistry.loadGetStatusPlugins() + assert(plugins.size == 1) + assert(plugins.head.isInstanceOf[GetStatusPlugin]) + } + } + + test("Multiple GetStatus plugins loaded dynamically from config") { + withSparkConf( + Connect.CONNECT_EXTENSIONS_GET_STATUS_CLASSES.key -> + ("org.apache.spark.sql.connect.plugin.DummyGetStatusPlugin," + + "org.apache.spark.sql.connect.plugin.DummyGetStatusPlugin")) { + val plugins = SparkConnectPluginRegistry.loadGetStatusPlugins() + assert(plugins.size == 2) + plugins.foreach(p => assert(p.isInstanceOf[GetStatusPlugin])) + } + } + test("Building builders using factory methods") { val x = SparkConnectPluginRegistry.relation[DummyPlugin](classOf[DummyPlugin]) assert(x != null) @@ -247,6 +289,10 @@ class SparkConnectPluginRegistrySuite extends SharedSparkSession with SparkConne SparkConnectPluginRegistry.expression[DummyExpressionPlugin](classOf[DummyExpressionPlugin]) assert(y != null) assert(y().isInstanceOf[ExpressionPlugin]) + val z = + SparkConnectPluginRegistry.getStatus[DummyGetStatusPlugin](classOf[DummyGetStatusPlugin]) + assert(z != null) + assert(z().isInstanceOf[GetStatusPlugin]) } test("Configured class not found is properly thrown") { @@ -265,6 +311,14 @@ class SparkConnectPluginRegistrySuite extends SharedSparkSession with SparkConne SparkEnv.get.conf.get(Connect.CONNECT_EXTENSIONS_RELATION_CLASSES)) } } + + withSparkConf( + Connect.CONNECT_EXTENSIONS_GET_STATUS_CLASSES.key -> "this.class.does.not.exist") { + assertThrows[ClassNotFoundException] { + SparkConnectPluginRegistry.createConfiguredPlugins( + SparkEnv.get.conf.get(Connect.CONNECT_EXTENSIONS_GET_STATUS_CLASSES)) + } + } } } diff --git a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/ExecuteEventsManagerSuite.scala b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/ExecuteEventsManagerSuite.scala index a17c76ae95286..a96d0ab977c5c 100644 --- a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/ExecuteEventsManagerSuite.scala +++ b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/ExecuteEventsManagerSuite.scala @@ -341,6 +341,64 @@ class ExecuteEventsManagerSuite } } + test("terminationReason is None initially") { + val events = setupEvents(ExecuteStatus.Pending) + assert(events.terminationReason.isEmpty) + } + + test("terminationReason is set to Succeeded after postFinished") { + val events = setupEvents(ExecuteStatus.Started) + assert(events.terminationReason.isEmpty) + events.postFinished() + assert(events.terminationReason.contains(TerminationReason.Succeeded)) + } + + test("terminationReason is set to Failed after postFailed") { + val events = setupEvents(ExecuteStatus.Started) + assert(events.terminationReason.isEmpty) + events.postFailed(DEFAULT_ERROR) + assert(events.terminationReason.contains(TerminationReason.Failed)) + } + + test("terminationReason is set to Canceled after postCanceled") { + val events = setupEvents(ExecuteStatus.Started) + assert(events.terminationReason.isEmpty) + events.postCanceled() + assert(events.terminationReason.contains(TerminationReason.Canceled)) + } + + test("terminationReason remains unchanged after postClosed") { + val events = setupEvents(ExecuteStatus.Started) + events.postFinished() + assert(events.terminationReason.contains(TerminationReason.Succeeded)) + events.postClosed() + assert(events.terminationReason.contains(TerminationReason.Succeeded)) + } + + test("terminationReason: Canceled takes precedence over Succeeded") { + val events = setupEvents(ExecuteStatus.Started) + events.postFinished() + assert(events.terminationReason.contains(TerminationReason.Succeeded)) + events.postCanceled() + assert(events.terminationReason.contains(TerminationReason.Canceled)) + } + + test("terminationReason: Canceled takes precedence over Failed") { + val events = setupEvents(ExecuteStatus.Started) + events.postFailed(DEFAULT_ERROR) + assert(events.terminationReason.contains(TerminationReason.Failed)) + events.postCanceled() + assert(events.terminationReason.contains(TerminationReason.Canceled)) + } + + test("terminationReason: Failed takes precedence over Succeeded") { + val events = setupEvents(ExecuteStatus.Started) + events.postFinished() + assert(events.terminationReason.contains(TerminationReason.Succeeded)) + events.postFailed(DEFAULT_ERROR) + assert(events.terminationReason.contains(TerminationReason.Failed)) + } + def setupEvents( executeStatus: ExecuteStatus, sessionStatus: SessionStatus = SessionStatus.Started): ExecuteEventsManager = { diff --git a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/GetStatusHandlerSuite.scala b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/GetStatusHandlerSuite.scala new file mode 100644 index 0000000000000..21d96fd8a87d8 --- /dev/null +++ b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/GetStatusHandlerSuite.scala @@ -0,0 +1,354 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.spark.sql.connect.service + +import java.util +import java.util.{Optional, UUID} + +import scala.concurrent.Promise +import scala.concurrent.duration._ +import scala.jdk.CollectionConverters._ + +import com.google.protobuf +import com.google.protobuf.StringValue +import io.grpc.stub.StreamObserver + +import org.apache.spark.connect.proto +import org.apache.spark.connect.proto.GetStatusResponse +import org.apache.spark.sql.connect.SparkConnectTestUtils +import org.apache.spark.sql.connect.plugin.{GetStatusPlugin, SparkConnectPluginRegistry} +import org.apache.spark.sql.test.SharedSparkSession +import org.apache.spark.util.ThreadUtils + +/** + * A test-only base class for GetStatusPlugins that echo extensions back with configurable + * prefixes. For each input extension containing a StringValue, it produces a response extension + * with the value prefixed by "{requestPrefix}" or "{opPrefix}{operationId}:". + */ +abstract class EchoGetStatusPluginBase(requestPrefix: String, opPrefix: String) + extends GetStatusPlugin { + + override def processRequestExtensions( + sessionHolder: SessionHolder, + requestExtensions: util.List[protobuf.Any]): Optional[util.List[protobuf.Any]] = + echoWithPrefix(requestExtensions, requestPrefix) + + override def processOperationExtensions( + operationId: String, + sessionHolder: SessionHolder, + operationExtensions: util.List[protobuf.Any]): Optional[util.List[protobuf.Any]] = + echoWithPrefix(operationExtensions, s"$opPrefix$operationId:") + + private def echoWithPrefix( + extensions: util.List[protobuf.Any], + prefix: String): Optional[util.List[protobuf.Any]] = { + if (extensions.isEmpty) return Optional.empty() + val result = new util.ArrayList[protobuf.Any]() + extensions.forEach { ext => + if (ext.is(classOf[StringValue])) { + val value = ext.unpack(classOf[StringValue]).getValue + result.add(protobuf.Any.pack(StringValue.of(s"$prefix$value"))) + } + } + Optional.of(result) + } +} + +class EchoGetStatusPlugin extends EchoGetStatusPluginBase("request-echo:", "op-echo:") + +class SecondEchoGetStatusPlugin extends EchoGetStatusPluginBase("second-request:", "second-op:") + +/** + * A no-op plugin that always returns Optional.empty() for both request and operation extensions. + */ +class NoOpGetStatusPlugin extends GetStatusPlugin { + override def processRequestExtensions( + sessionHolder: SessionHolder, + requestExtensions: util.List[protobuf.Any]): Optional[util.List[protobuf.Any]] = + Optional.empty() + + override def processOperationExtensions( + operationId: String, + sessionHolder: SessionHolder, + operationExtensions: util.List[protobuf.Any]): Optional[util.List[protobuf.Any]] = + Optional.empty() +} + +/** + * A plugin that always throws a RuntimeException. + */ +class FailingGetStatusPlugin extends GetStatusPlugin { + override def processRequestExtensions( + sessionHolder: SessionHolder, + requestExtensions: util.List[protobuf.Any]): Optional[util.List[protobuf.Any]] = + throw new RuntimeException("request plugin failure") + + override def processOperationExtensions( + operationId: String, + sessionHolder: SessionHolder, + operationExtensions: util.List[protobuf.Any]): Optional[util.List[protobuf.Any]] = + throw new RuntimeException("operation plugin failure") +} + +class GetStatusHandlerSuite extends SharedSparkSession { + + // Default userId matching SparkConnectTestUtils.createDummySessionHolder default + private val defaultUserId = "testUser" + + protected override def afterEach(): Unit = { + super.afterEach() + SparkConnectService.sessionManager.invalidateAllSessions() + SparkConnectPluginRegistry.reset() + } + + private def sendGetStatusRequest( + sessionId: String, + userId: String = defaultUserId, + serverSideSessionId: Option[String] = None, + requestExtensions: Seq[protobuf.Any] = Seq.empty, + customize: proto.GetStatusRequest.Builder => Unit = _ => ()): GetStatusResponse = { + val userContext = proto.UserContext.newBuilder().setUserId(userId).build() + val requestBuilder = proto.GetStatusRequest + .newBuilder() + .setUserContext(userContext) + .setSessionId(sessionId) + + requestExtensions.foreach(requestBuilder.addExtensions) + serverSideSessionId.foreach(requestBuilder.setClientObservedServerSideSessionId) + customize(requestBuilder) + + val request = requestBuilder.build() + val responseObserver = new GetStatusResponseObserver() + val handler = new SparkConnectGetStatusHandler(responseObserver) + handler.handle(request) + + ThreadUtils.awaitResult(responseObserver.promise.future, 10.seconds) + } + + private def sendGetOperationStatusRequest( + sessionId: String, + operationIds: Seq[String] = Seq.empty, + userId: String = defaultUserId, + serverSideSessionId: Option[String] = None, + requestExtensions: Seq[protobuf.Any] = Seq.empty, + operationExtensions: Seq[protobuf.Any] = Seq.empty): GetStatusResponse = { + sendGetStatusRequest( + sessionId, + userId, + serverSideSessionId, + requestExtensions, + { builder => + val operationStatusRequest = proto.GetStatusRequest.OperationStatusRequest.newBuilder() + operationIds.foreach(operationStatusRequest.addOperationIds) + operationExtensions.foreach(operationStatusRequest.addExtensions) + builder.setOperationStatus(operationStatusRequest) + }) + } + + test("GetStatus returns session info for new session") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val response = sendGetStatusRequest(sessionHolder.sessionId, userId = sessionHolder.userId) + + assert(response.getSessionId == sessionHolder.sessionId) + assert(response.getServerSideSessionId.nonEmpty) + } + + test("GetStatus without operation IDs returns all existing operations") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val command = proto.Command.newBuilder().build() + val executeHolder1 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val executeHolder2 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val executeHolder3 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + + val response = + sendGetOperationStatusRequest(sessionHolder.sessionId, userId = sessionHolder.userId) + + val statuses = response.getOperationStatusesList.asScala + assert(statuses.size == 3) + val operationIds = statuses.map(_.getOperationId).toSet + assert(operationIds.contains(executeHolder1.operationId)) + assert(operationIds.contains(executeHolder2.operationId)) + assert(operationIds.contains(executeHolder3.operationId)) + } + + test("GetStatus returns UNKNOWN status for non-existent operation ID") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val nonExistentOperationId = UUID.randomUUID().toString + + val response = sendGetOperationStatusRequest( + sessionHolder.sessionId, + Seq(nonExistentOperationId), + userId = sessionHolder.userId) + + val statuses = response.getOperationStatusesList.asScala + assert(statuses.size == 1) + assert(statuses.head.getOperationId == nonExistentOperationId) + assert( + statuses.head.getState == + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_UNKNOWN) + } + + test("GetStatus returns RUNNING status for active operation") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val command = proto.Command.newBuilder().build() + val executeHolder = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + + // The execute holder is created with Started status by createDummyExecuteHolder + val response = sendGetOperationStatusRequest( + sessionHolder.sessionId, + Seq(executeHolder.operationId), + sessionHolder.userId) + + val statuses = response.getOperationStatusesList.asScala + assert(statuses.size == 1) + assert(statuses.head.getOperationId == executeHolder.operationId) + assert( + statuses.head.getState == + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_RUNNING) + } + + test("GetStatus propagates both request and operation extensions via plugin") { + SparkConnectPluginRegistry.setGetStatusPluginsForTesting(Seq(new EchoGetStatusPlugin())) + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val command = proto.Command.newBuilder().build() + val executeHolder1 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val executeHolder2 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + + val reqExt = protobuf.Any.pack(StringValue.of("req-data")) + val opExt = protobuf.Any.pack(StringValue.of("op-data")) + val response = sendGetOperationStatusRequest( + sessionHolder.sessionId, + operationIds = Seq(executeHolder1.operationId, executeHolder2.operationId), + userId = sessionHolder.userId, + requestExtensions = Seq(reqExt), + operationExtensions = Seq(opExt)) + + // Verify request-level extensions + val responseExtensions = response.getExtensionsList.asScala + assert(responseExtensions.size == 1) + assert( + responseExtensions.head.unpack(classOf[StringValue]).getValue == "request-echo:req-data") + + // Verify operation-level extensions for both operations + val statuses = response.getOperationStatusesList.asScala + assert(statuses.size == 2) + + val statusByOpId = statuses.map(s => s.getOperationId -> s).toMap + Seq(executeHolder1, executeHolder2).foreach { holder => + val opStatus = statusByOpId(holder.operationId) + assert( + opStatus.getState == + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_RUNNING) + + val opExtensions = opStatus.getExtensionsList.asScala + assert(opExtensions.size == 1) + assert( + opExtensions.head.unpack(classOf[StringValue]).getValue == + s"op-echo:${holder.operationId}:op-data") + } + } + + test("GetStatus with no plugin returns no extensions") { + SparkConnectPluginRegistry.setGetStatusPluginsForTesting(Seq.empty) + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val operationId = UUID.randomUUID().toString + + val reqExt = protobuf.Any.pack(StringValue.of("ignored")) + val opExt = protobuf.Any.pack(StringValue.of("also-ignored")) + val response = sendGetOperationStatusRequest( + sessionHolder.sessionId, + operationIds = Seq(operationId), + userId = sessionHolder.userId, + requestExtensions = Seq(reqExt), + operationExtensions = Seq(opExt)) + + assert(response.getExtensionsList.isEmpty) + val statuses = response.getOperationStatusesList.asScala + assert(statuses.size == 1) + assert(statuses.head.getExtensionsList.isEmpty) + } + + test("GetStatus aggregates extensions from multiple plugins, skipping empty ones") { + SparkConnectPluginRegistry.setGetStatusPluginsForTesting( + Seq(new EchoGetStatusPlugin(), new NoOpGetStatusPlugin(), new SecondEchoGetStatusPlugin())) + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val command = proto.Command.newBuilder().build() + val executeHolder = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + + val reqExt = protobuf.Any.pack(StringValue.of("hello")) + val opExt = protobuf.Any.pack(StringValue.of("world")) + val response = sendGetOperationStatusRequest( + sessionHolder.sessionId, + operationIds = Seq(executeHolder.operationId), + userId = sessionHolder.userId, + requestExtensions = Seq(reqExt), + operationExtensions = Seq(opExt)) + + val responseExtValues = response.getExtensionsList.asScala + .map(_.unpack(classOf[StringValue]).getValue) + assert(responseExtValues.size == 2) + assert(responseExtValues.contains("request-echo:hello")) + assert(responseExtValues.contains("second-request:hello")) + + val statuses = response.getOperationStatusesList.asScala + assert(statuses.size == 1) + val opExtValues = statuses.head.getExtensionsList.asScala + .map(_.unpack(classOf[StringValue]).getValue) + assert(opExtValues.size == 2) + assert(opExtValues.contains(s"op-echo:${executeHolder.operationId}:world")) + assert(opExtValues.contains(s"second-op:${executeHolder.operationId}:world")) + } + + test("GetStatus chain isolates plugin failures and collects from healthy plugins") { + SparkConnectPluginRegistry.setGetStatusPluginsForTesting( + Seq( + new EchoGetStatusPlugin(), + new FailingGetStatusPlugin(), + new SecondEchoGetStatusPlugin())) + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val command = proto.Command.newBuilder().build() + val executeHolder = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + + val reqExt = protobuf.Any.pack(StringValue.of("safe")) + val opExt = protobuf.Any.pack(StringValue.of("safe")) + val response = sendGetOperationStatusRequest( + sessionHolder.sessionId, + operationIds = Seq(executeHolder.operationId), + userId = sessionHolder.userId, + requestExtensions = Seq(reqExt), + operationExtensions = Seq(opExt)) + + val responseExtValues = response.getExtensionsList.asScala + .map(_.unpack(classOf[StringValue]).getValue) + assert(responseExtValues.size == 2) + assert(responseExtValues.contains("request-echo:safe")) + assert(responseExtValues.contains("second-request:safe")) + + val opExtValues = response.getOperationStatusesList.asScala.head.getExtensionsList.asScala + .map(_.unpack(classOf[StringValue]).getValue) + assert(opExtValues.size == 2) + assert(opExtValues.contains(s"op-echo:${executeHolder.operationId}:safe")) + assert(opExtValues.contains(s"second-op:${executeHolder.operationId}:safe")) + } +} + +private class GetStatusResponseObserver extends StreamObserver[proto.GetStatusResponse] { + val promise: Promise[GetStatusResponse] = Promise() + override def onNext(value: proto.GetStatusResponse): Unit = promise.success(value) + override def onError(t: Throwable): Unit = promise.failure(t) + override def onCompleted(): Unit = {} +} diff --git a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/SparkConnectExecutionManagerSuite.scala b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/SparkConnectExecutionManagerSuite.scala new file mode 100644 index 0000000000000..228bb6e83a985 --- /dev/null +++ b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/SparkConnectExecutionManagerSuite.scala @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.spark.sql.connect.service + +import org.apache.spark.connect.proto +import org.apache.spark.sql.connect.SparkConnectTestUtils +import org.apache.spark.sql.test.SharedSparkSession + +/** + * Test suite for SparkConnectExecutionManager. + */ +class SparkConnectExecutionManagerSuite extends SharedSparkSession { + + protected override def afterEach(): Unit = { + super.afterEach() + SparkConnectService.sessionManager.invalidateAllSessions() + } + + private def executionManager: SparkConnectExecutionManager = { + SparkConnectService.executionManager + } + + test("tombstone is updated with Closed status after removeExecuteHolder with abandoned") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val command = proto.Command.newBuilder().build() + val executeHolder = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val executeKey = executeHolder.key + + executionManager.removeExecuteHolder(executeKey, abandoned = true) + + val tombstoneInfo = executionManager.getAbandonedTombstone(executeKey) + assert(tombstoneInfo.isDefined, "Tombstone should exist for abandoned operation") + + val info = tombstoneInfo.get + assert( + info.status == ExecuteStatus.Closed, + s"Expected Closed status in tombstone, got ${info.status}") + assert(info.closedTimeNs.isDefined, "closedTimeNs should be set after close()") + assert(info.closedTimeNs.get > 0, "closedTimeNs should be > 0") + } + + test("normal execution removal does not create tombstone") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val command = proto.Command.newBuilder().build() + val executeHolder = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val executeKey = executeHolder.key + + executionManager.removeExecuteHolder(executeKey) + + val tombstoneInfo = executionManager.getAbandonedTombstone(executeKey) + assert(tombstoneInfo.isEmpty, "Tombstone should not exist for normal (non-abandoned) removal") + } + + test("inactiveOperations cache has correct state after abandoned removal") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val command = proto.Command.newBuilder().build() + val executeHolder = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val operationId = executeHolder.operationId + + executionManager.removeExecuteHolder(executeHolder.key, abandoned = true) + + val inactiveInfo = sessionHolder.getInactiveOperationInfo(operationId) + assert(inactiveInfo.isDefined, "Operation should be in inactive operations cache") + + val info = inactiveInfo.get + assert( + info.status == ExecuteStatus.Closed, + s"Expected Closed status in inactive cache, got ${info.status}") + assert( + info.terminationReason.isDefined, + "terminationReason should be set by postCanceled and captured by closeOperation") + assert( + info.terminationReason.get == TerminationReason.Canceled, + s"Expected Canceled terminationReason for abandoned, got ${info.terminationReason}") + } + + test("inactiveOperations cache has correct state after normal removal") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val command = proto.Command.newBuilder().build() + val executeHolder = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val operationId = executeHolder.operationId + + assert( + sessionHolder.getOperationStatus(operationId).contains(true), + "Operation should be active before removal") + assert( + sessionHolder.getInactiveOperationInfo(operationId).isEmpty, + "Operation should not be in inactive cache before removal") + + executionManager.removeExecuteHolder(executeHolder.key) + + assert( + sessionHolder.getOperationStatus(operationId).contains(false), + "Operation should be inactive after removal") + val inactiveInfo = sessionHolder.getInactiveOperationInfo(operationId) + assert(inactiveInfo.isDefined, "Operation should be in inactive cache after removal") + + val info = inactiveInfo.get + assert(info.operationId == operationId, "Operation ID should match") + assert( + info.status == ExecuteStatus.Closed, + s"Expected Closed status in inactive cache, got ${info.status}") + } +} diff --git a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/SparkConnectSessionHolderSuite.scala b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/SparkConnectSessionHolderSuite.scala index 1b747705e9ad7..17402ab5ddb43 100644 --- a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/SparkConnectSessionHolderSuite.scala +++ b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/SparkConnectSessionHolderSuite.scala @@ -431,6 +431,94 @@ class SparkConnectSessionHolderSuite extends SharedSparkSession { assert(ex.getMessage.contains("already exists")) } + test("getInactiveOperationInfo returns TerminationInfo for closed operations") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val command = proto.Command.newBuilder().build() + val executeHolder = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val operationId = executeHolder.operationId + + sessionHolder.closeOperation(executeHolder) + + val inactiveInfo = sessionHolder.getInactiveOperationInfo(operationId) + assert(inactiveInfo.isDefined) + assert(inactiveInfo.get.operationId == operationId) + } + + test("getInactiveOperationInfo returns None for active operations") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + val command = proto.Command.newBuilder().build() + val executeHolder = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val operationId = executeHolder.operationId + + assert(sessionHolder.getInactiveOperationInfo(operationId) == None) + } + + test("getInactiveOperationInfo returns None for unknown operations") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + assert(sessionHolder.getInactiveOperationInfo("unknown-op") == None) + } + + test("listInactiveOperations returns all closed operations") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + + val command = proto.Command.newBuilder().build() + val executeHolder1 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val executeHolder2 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val executeHolder3 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + + sessionHolder.closeOperation(executeHolder1) + sessionHolder.closeOperation(executeHolder2) + sessionHolder.closeOperation(executeHolder3) + + val inactiveOps = sessionHolder.listInactiveOperations() + assert(inactiveOps.size == 3) + val inactiveOpIds = inactiveOps.map(_.operationId).toSet + assert(inactiveOpIds.contains(executeHolder1.operationId)) + assert(inactiveOpIds.contains(executeHolder2.operationId)) + assert(inactiveOpIds.contains(executeHolder3.operationId)) + } + + test("listInactiveOperations returns empty for new session") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + assert(sessionHolder.listInactiveOperations().isEmpty) + } + + test("listActiveOperationIds returns all active operations") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + + val command = proto.Command.newBuilder().build() + val executeHolder1 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val executeHolder2 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val executeHolder3 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + + val activeOps = sessionHolder.listActiveOperationIds() + assert(activeOps.size == 3) + val activeOpIds = activeOps.toSet + assert(activeOpIds.contains(executeHolder1.operationId)) + assert(activeOpIds.contains(executeHolder2.operationId)) + assert(activeOpIds.contains(executeHolder3.operationId)) + } + + test("listActiveOperationIds returns empty for new session") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + assert(sessionHolder.listActiveOperationIds().isEmpty) + } + + test("listActiveOperationIds excludes closed operations") { + val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) + + val command = proto.Command.newBuilder().build() + val executeHolder1 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + val executeHolder2 = SparkConnectTestUtils.createDummyExecuteHolder(sessionHolder, command) + + sessionHolder.closeOperation(executeHolder1) + + val activeOps = sessionHolder.listActiveOperationIds() + assert(activeOps.size == 1) + assert(activeOps.contains(executeHolder2.operationId)) + assert(!activeOps.contains(executeHolder1.operationId)) + } + test("Pipeline execution cache") { val sessionHolder = SparkConnectTestUtils.createDummySessionHolder(spark) val graphId = "test_graph" From f9a9c9402c929478ba23c1a000d6dbbabbed7b13 Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Wed, 25 Feb 2026 09:14:19 -0800 Subject: [PATCH 034/130] [SPARK-55683][SQL] Optimize `VectorizedPlainValuesReader.readUnsignedLongs` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? This PR optimizes `VectorizedPlainValuesReader.readUnsignedLongs` by replacing the per-element `BigInteger` heap allocation chain with direct byte manipulation. The original implementation allocates multiple objects per element: ```java // Old: String + BigInteger + internal int[] + byte[] allocations per element c.putByteArray(rowId + i, new BigInteger(Long.toUnsignedString(buffer.getLong())).toByteArray()); ``` The new implementation reads raw little-endian bytes directly from the `ByteBuffer` backing array (when available) and converts them to `BigInteger`-compatible big-endian encoding in a single pass: ```java // New: hasArray() fast path - operates directly on backing array, one byte[] per element if (buffer.hasArray()) { byte[] src = buffer.array(); int offset = buffer.arrayOffset() + buffer.position(); for (int i = 0; i < total; i++, rowId++, offset += 8) { putLittleEndianBytesAsBigInteger(c, rowId, src, offset); } } else { byte[] data = new byte[8]; // reused across all values in this batch for (int i = 0; i < total; i++, rowId++) { buffer.get(data); putLittleEndianBytesAsBigInteger(c, rowId, data, 0); } } ``` The private helper `putLittleEndianBytesAsBigInteger` handles the conversion with output matching `BigInteger.toByteArray()` semantics: - **Zero value**: writes `[0x00]` (1 byte) rather than an empty array, since `new BigInteger(new byte[0])` throws `NumberFormatException` - **Sign byte**: prepends `0x00` when the most significant byte has bit 7 set, to ensure the value is interpreted as positive by `BigInteger` - **Byte order**: reverses little-endian Parquet physical encoding to big-endian in a single loop ### Why are the changes needed? The original implementation constructs a `BigInteger` via `Long.toUnsignedString` + `new BigInteger(String)`, which involves per-element allocations of a `String`, a `BigInteger`, its internal `int[]` magnitude array, and the final `byte[]`. For a typical batch of 4096 values this means ~16K object allocations, creating significant GC pressure in workloads reading large `UINT_64` columns. The new implementation reduces this to one `byte[]` allocation per element by operating directly on the raw bytes from the `ByteBuffer`, avoiding all intermediate object creation. Additionally, the direct buffer fallback path reuses a single `byte[8]` scratch buffer across the entire batch. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? - The existing test `SPARK-34817: Read UINT_64 as Decimal from parquet` in `ParquetIOSuite` was extended with boundary values covering the critical edge cases of the new byte manipulation logic - Rename the original code to `OldVectorizedPlainValuesReader`, and compare the latency of the old and new `readUnsignedLongs` methods using JMH:

Benchmark Code (click to expand) ```java package org.apache.spark.sql.execution.datasources.parquet; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Random; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import org.apache.parquet.bytes.ByteBufferInputStream; import org.apache.spark.sql.execution.vectorized.OnHeapColumnVector; import org.apache.spark.sql.execution.vectorized.WritableColumnVector; import org.apache.spark.sql.types.DataTypes; BenchmarkMode(Mode.AverageTime) OutputTimeUnit(TimeUnit.MICROSECONDS) State(Scope.Thread) Fork(value = 1, jvmArgs = {"-Xms4G", "-Xmx4G"}) Warmup(iterations = 5, time = 1) Measurement(iterations = 10, time = 1) public class VectorizedPlainValuesReaderJMHBenchmark { // ==================== Parameters ==================== Param({"10000000"}) private int numValues; // ==================== Test Data ==================== private byte[] longData; private static final int BATCH_SIZE = 4096; private OldVectorizedPlainValuesReader oldSingleBufferOnHeapReader; private OldVectorizedPlainValuesReader oldSingleBufferOffHeapReader; private VectorizedPlainValuesReader newSingleBufferOnHeapReader; private VectorizedPlainValuesReader newSingleBufferOffHeapReader; // ==================== State Classes ==================== /** * Column vector state using DecimalType(20, 0), which is the correct type for UINT64. * Parquet UINT_64 logical type is mapped to DecimalType(20, 0) in Spark. * Using LongType would cause NullPointerException because readUnsignedLongs * calls arrayData() which requires childColumns, only initialized for DecimalType. */ State(Scope.Thread) public static class DecimalColumnVectorState { public WritableColumnVector decimalColumn; Setup(Level.Iteration) public void setup() { // UINT64 -> DecimalType(20, 0): precision=20, scale=0 decimalColumn = new OnHeapColumnVector(BATCH_SIZE, DataTypes.createDecimalType(20, 0)); } TearDown(Level.Iteration) public void tearDown() { decimalColumn.close(); } Setup(Level.Invocation) public void reset() { decimalColumn.reset(); } } // ==================== Setup ==================== Setup(Level.Trial) public void setupTrial() { Random random = new Random(42); longData = generateLongData(numValues, random); } Setup(Level.Invocation) public void setupInvocation() throws IOException { oldSingleBufferOnHeapReader = new OldVectorizedPlainValuesReader(); oldSingleBufferOnHeapReader.initFromPage(numValues, createSingleBufferInputStream(longData)); oldSingleBufferOffHeapReader = new OldVectorizedPlainValuesReader(); oldSingleBufferOffHeapReader.initFromPage(numValues, createDirectSingleBufferInputStream(longData)); newSingleBufferOnHeapReader = new VectorizedPlainValuesReader(); newSingleBufferOnHeapReader.initFromPage(numValues, createSingleBufferInputStream(longData)); newSingleBufferOffHeapReader = new VectorizedPlainValuesReader(); newSingleBufferOffHeapReader.initFromPage(numValues, createDirectSingleBufferInputStream(longData)); } // ==================== Data Generation ==================== private byte[] generateLongData(int count, Random random) { ByteBuffer buffer = ByteBuffer.allocate(count * 8).order(ByteOrder.LITTLE_ENDIAN); for (int i = 0; i < count; i++) { buffer.putLong(random.nextLong()); // full unsigned long range } return buffer.array(); } // ==================== ByteBufferInputStream Creation ==================== private ByteBufferInputStream createSingleBufferInputStream(byte[] data) { ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN); return ByteBufferInputStream.wrap(buffer); } private ByteBuffer createDirectBuffer(byte[] data) { ByteBuffer buffer = ByteBuffer.allocateDirect(data.length).order(ByteOrder.LITTLE_ENDIAN); buffer.put(data); buffer.flip(); return buffer; } private ByteBufferInputStream createDirectSingleBufferInputStream(byte[] data) { ByteBuffer buffer = createDirectBuffer(data); return ByteBufferInputStream.wrap(buffer); } // ==================================================================================== // readUnsignedLongs onHeap // ==================================================================================== Benchmark public void readUnsignedLongs_onHeap_Old(DecimalColumnVectorState state) throws IOException { for (int i = 0; i < numValues; i += BATCH_SIZE) { oldSingleBufferOnHeapReader.readUnsignedLongs( Math.min(BATCH_SIZE, numValues - i), state.decimalColumn, 0); } } Benchmark public void readUnsignedLongs_onHeap_New(DecimalColumnVectorState state) throws IOException { for (int i = 0; i < numValues; i += BATCH_SIZE) { newSingleBufferOnHeapReader.readUnsignedLongs( Math.min(BATCH_SIZE, numValues - i), state.decimalColumn, 0); } } // ==================================================================================== // readUnsignedLongs offHeap // ==================================================================================== Benchmark public void readUnsignedLongs_offHeap_Old(DecimalColumnVectorState state) throws IOException { for (int i = 0; i < numValues; i += BATCH_SIZE) { oldSingleBufferOffHeapReader.readUnsignedLongs( Math.min(BATCH_SIZE, numValues - i), state.decimalColumn, 0); } } Benchmark public void readUnsignedLongs_offHeap_New(DecimalColumnVectorState state) throws IOException { for (int i = 0; i < numValues; i += BATCH_SIZE) { newSingleBufferOffHeapReader.readUnsignedLongs( Math.min(BATCH_SIZE, numValues - i), state.decimalColumn, 0); } } // ==================== Main Method ==================== public static void main(String[] args) throws RunnerException { String filter = args.length > 0 ? args[0] : VectorizedPlainValuesReaderJMHBenchmark.class.getSimpleName(); Options opt = new OptionsBuilder() .include(filter) .build(); new Runner(opt).run(); } } ```
Perform `build/sbt "sql/Test/runMain org.apache.spark.sql.execution.datasources.parquet.VectorizedPlainValuesReaderJMHBenchmark"` to conduct the test **Benchmark results:** - Java 17.0.18+8-LTS ``` Benchmark (numValues) Mode Cnt Score Error Units VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_offHeap_New 10000000 avgt 10 249413.824 ± 12242.331 us/op VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_offHeap_Old 10000000 avgt 10 2301279.127 ± 14970.249 us/op VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_onHeap_New 10000000 avgt 10 282651.747 ± 5031.717 us/op VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_onHeap_Old 10000000 avgt 10 2382690.093 ± 10364.228 us/op ``` - Java 21.0.10+7-LTS ``` Benchmark (numValues) Mode Cnt Score Error Units VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_offHeap_New 10000000 avgt 10 256621.630 ± 24087.509 us/op VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_offHeap_Old 10000000 avgt 10 2120170.591 ± 4862.317 us/op VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_onHeap_New 10000000 avgt 10 284058.229 ± 19966.179 us/op VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_onHeap_Old 10000000 avgt 10 2190838.305 ± 7979.740 us/op ``` Both onHeap and offHeap paths show approximately **~8x** improvement. ### Was this patch authored or co-authored using generative AI tooling? Yes, Claude Sonnet 4.6 was used to assist in completing the code writing. Closes #54479 from LuciferYang/SPARK-55683. Authored-by: yangjie01 Signed-off-by: Dongjoon Hyun --- .../parquet/VectorizedPlainValuesReader.java | 81 ++++++++++++++++++- .../datasources/parquet/ParquetIOSuite.scala | 18 ++++- 2 files changed, 91 insertions(+), 8 deletions(-) diff --git a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java index a040a8990bad3..9ad07a1ff5eeb 100644 --- a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java +++ b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java @@ -17,7 +17,6 @@ package org.apache.spark.sql.execution.datasources.parquet; import java.io.IOException; -import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -199,10 +198,84 @@ public void skipLongs(int total) { public final void readUnsignedLongs(int total, WritableColumnVector c, int rowId) { int requiredBytes = total * 8; ByteBuffer buffer = getBuffer(requiredBytes); - for (int i = 0; i < total; i += 1) { - c.putByteArray( - rowId + i, new BigInteger(Long.toUnsignedString(buffer.getLong())).toByteArray()); + if (buffer.hasArray()) { + byte[] src = buffer.array(); + int offset = buffer.arrayOffset() + buffer.position(); + for (int i = 0; i < total; i++, rowId++, offset += 8) { + putLittleEndianBytesAsBigInteger(c, rowId, src, offset); + } + } else { + // direct buffer fallback: copy 8 bytes per value + byte[] data = new byte[8]; + for (int i = 0; i < total; i++, rowId++) { + buffer.get(data); + putLittleEndianBytesAsBigInteger(c, rowId, data, 0); + } + } + } + + /** + * Writes 8 little-endian bytes from {@code src[offset..offset+7]} into {@code c} at + * {@code rowId} as a big-endian byte array compatible with {@link java.math.BigInteger} + * two's-complement encoding. + * + *

The output matches the semantics of {@link java.math.BigInteger#toByteArray()}: + *

    + *
  • Big-endian byte order
  • + *
  • Minimal encoding: no unnecessary leading zero bytes
  • + *
  • A {@code 0x00} sign byte is prepended if the most significant byte has bit 7 + * set, ensuring the value is interpreted as positive by {@code BigInteger}
  • + *
  • Zero is encoded as {@code [0x00]} (1 byte), not an empty array, because + * {@code new BigInteger(new byte[0])} throws {@link NumberFormatException}
  • + *
+ * + *

This is used by {@link #readUnsignedLongs} to store Parquet {@code UINT_64} values + * into a {@code DecimalType(20, 0)} column vector, where each value is stored as a + * byte array in {@code arrayData()} and later reconstructed via + * {@code new BigInteger(bytes)}. + * + * @param c the target column vector; must be of {@code DecimalType(20, 0)} + * @param rowId the row index to write into + * @param src the source byte array containing little-endian encoded data + * @param offset the starting position in {@code src}; reads bytes + * {@code src[offset..offset+7]} + */ + private static void putLittleEndianBytesAsBigInteger( + WritableColumnVector c, int rowId, byte[] src, int offset) { + // src is little-endian; the most significant byte is at src[offset + 7]. + // Scan from the most significant end to find the first non-zero byte, + // which determines the minimal number of bytes needed for encoding. + int msbIndex = offset + 7; + while (msbIndex > offset && src[msbIndex] == 0) { + msbIndex--; + } + + // Zero value: must write [0x00] rather than an empty array. + // BigInteger.ZERO.toByteArray() returns [0x00], and new BigInteger(new byte[0]) + // throws NumberFormatException("Zero length BigInteger"). + if (msbIndex == offset && src[offset] == 0) { + c.putByteArray(rowId, new byte[]{0}); + return; + } + + // Prepend a 0x00 sign byte if the most significant byte has bit 7 set. + // This matches BigInteger.toByteArray() behavior: positive values whose highest + // magnitude byte has the MSB set are prefixed with 0x00 to distinguish them + // from negative values in two's-complement encoding. + boolean needSignByte = (src[msbIndex] & 0x80) != 0; + int valueLen = msbIndex - offset + 1; + int totalLen = needSignByte ? valueLen + 1 : valueLen; + + byte[] dest = new byte[totalLen]; + int destOffset = 0; + if (needSignByte) { + dest[destOffset++] = 0x00; + } + // Reverse byte order: little-endian src → big-endian dest + for (int i = msbIndex; i >= offset; i--) { + dest[destOffset++] = src[i]; } + c.putByteArray(rowId, dest, 0, totalLen); } // A fork of `readLongs` to rebase the timestamp values. For performance reasons, this method diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/parquet/ParquetIOSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/parquet/ParquetIOSuite.scala index 3072657a0954f..b52a464c5bd21 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/parquet/ParquetIOSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/parquet/ParquetIOSuite.scala @@ -17,6 +17,7 @@ package org.apache.spark.sql.execution.datasources.parquet +import java.math.{BigDecimal => JBigDecimal} import java.time.{LocalDateTime, LocalTime} import java.util.Locale @@ -1261,11 +1262,17 @@ class ParquetIOSuite extends QueryTest with ParquetTest with SharedSparkSession val writer = createParquetWriter(schema, path, dictionaryEnabled) val factory = new SimpleGroupFactory(schema) + // Original range retained to avoid regression (-500 until 500).foreach { i => val group = factory.newGroup() .append("a", i % 100L) writer.write(group) } + // Boundary values: zero, one, signed extremes interpreted as unsigned + Seq(0L, 1L, Long.MaxValue, Long.MinValue, -2L, -1L).foreach { v => + val group = factory.newGroup().append("a", v) + writer.write(group) + } writer.close() } @@ -1273,10 +1280,13 @@ class ParquetIOSuite extends QueryTest with ParquetTest with SharedSparkSession val path = new Path(dir.toURI.toString, "part-r-0.parquet") makeRawParquetFile(path) readParquetFile(path.toString) { df => - checkAnswer(df, (-500 until 500).map { i => - val bi = UnsignedLong.fromLongBits(i % 100L).bigIntegerValue() - Row(new java.math.BigDecimal(bi)) - }) + val originalExpected = (-500 until 500).map { i => + Row(new JBigDecimal(UnsignedLong.fromLongBits(i % 100L).bigIntegerValue())) + } + val boundaryExpected = Seq(0L, 1L, Long.MaxValue, Long.MinValue, -2L, -1L).map { v => + Row(new JBigDecimal(UnsignedLong.fromLongBits(v).bigIntegerValue())) + } + checkAnswer(df, originalExpected ++ boundaryExpected) } } } From 54ff4ea05135e2366f271b5aaeaac45b4eba6481 Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Wed, 25 Feb 2026 09:19:10 -0800 Subject: [PATCH 035/130] [SPARK-55322][SQL][TESTS][FOLLOWUP] Fix `max_by and min_by with k` failure when ANSI mode is disabled ### What changes were proposed in this pull request? This pr updates a test case in `DataFrameAggregateSuite` regarding `max_by` and `min_by` functions. Specifically, it refines the assertion logic for invalid `k` input (non-numeric string) to account for different behaviors depending on `spark.sql.ansi.enabled`. - **ANSI Enabled**: Expects `CAST_INVALID_INPUT` or "cannot be cast" error, as the string `'two'` cannot be cast to an integer. - **ANSI Disabled**: Expects `VALUE_OUT_OF_RANGE` error. In legacy mode, the invalid cast returns `0` (default for integer), which then triggers a validation error because `k` must be positive. ### Why are the changes needed? Restore daily testing in non-ANSI mode - https://github.com/apache/spark/actions/runs/22247813526/job/64365502163 ``` [info] - max_by and min_by with k *** FAILED *** (1 second, 431 milliseconds) [info] "[DATATYPE_MISMATCH.VALUE_OUT_OF_RANGE] Cannot resolve "max_by(x, y, two)" due to data type mismatch: The `k` must be between [1, 100000] (current value = 0). SQLSTATE: 42K09; line 1 pos 7; [info] 'Aggregate [unresolvedalias(max_by(x#628078, y#628079, cast(two as int), false, 0, 0))] [info] +- SubqueryAlias tab [info] +- LocalRelation [x#628078, y#628079] [info] " did not contain "CAST_INVALID_INPUT", and "[DATATYPE_MISMATCH.VALUE_OUT_OF_RANGE] Cannot resolve "max_by(x, y, two)" due to data type mismatch: The `k` must be between [1, 100000] (current value = 0). SQLSTATE: 42K09; line 1 pos 7; [info] 'Aggregate [unresolvedalias(max_by(x#628078, y#628079, cast(two as int), false, 0, 0))] [info] +- SubqueryAlias tab [info] +- LocalRelation [x#628078, y#628079] [info] " did not contain "cannot be cast" (DataFrameAggregateSuite.scala:1386) ... [info] *** 4 TESTS FAILED *** [error] Failed: Total 4096, Failed 4, Errors 0, Passed 4092, Ignored 13 [error] Failed tests: [error] org.apache.spark.sql.SingleLevelAggregateHashMapSuite [error] org.apache.spark.sql.DataFrameAggregateSuite [error] org.apache.spark.sql.TwoLevelAggregateHashMapSuite [error] org.apache.spark.sql.TwoLevelAggregateHashMapWithVectorizedMapSuite [error] (sql / Test / test) sbt.TestsFailedException: Tests unsuccessful ``` ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Manually verify by running the command `SPARK_ANSI_SQL_MODE=false build/sbt "sql/testOnly org.apache.spark.sql.SingleLevelAggregateHashMapSuite org.apache.spark.sql.DataFrameAggregateSuite org.apache.spark.sql.TwoLevelAggregateHashMapSuite org.apache.spark.sql.TwoLevelAggregateHashMapWithVectorizedMapSuite"`, and all tests pass successfully. ### Was this patch authored or co-authored using generative AI tooling? No Closes #54484 from LuciferYang/SPARK-55322-FOLLOWUP. Authored-by: yangjie01 Signed-off-by: Dongjoon Hyun --- .../org/apache/spark/sql/DataFrameAggregateSuite.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/DataFrameAggregateSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/DataFrameAggregateSuite.scala index 64b33ccb89a2e..f606c6746f3c2 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/DataFrameAggregateSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/DataFrameAggregateSuite.scala @@ -1383,8 +1383,12 @@ class DataFrameAggregateSuite extends QueryTest val error = intercept[Exception] { sql(s"SELECT $fn(x, y, 'two') FROM VALUES (('a', 10)) AS tab(x, y)").collect() } - assert(error.getMessage.contains("CAST_INVALID_INPUT") || - error.getMessage.contains("cannot be cast")) + if (conf.ansiEnabled) { + assert(error.getMessage.contains("CAST_INVALID_INPUT") || + error.getMessage.contains("cannot be cast")) + } else { + assert(error.getMessage.contains("VALUE_OUT_OF_RANGE")) + } } // Error: k must be positive From 0444c02d3ba48acff79443f1a842c28e625ee43f Mon Sep 17 00:00:00 2001 From: tangrizzly Date: Wed, 25 Feb 2026 09:27:36 -0800 Subject: [PATCH 036/130] [SPARK-55155] Fix SET CATALOG to use special chars and backticks in the identifier name ### What changes were proposed in this pull request? This PR fixes the handling of catalog names with special characters in the `SET CATALOG` command. The changes modify `ResolveSetCatalogCommand` to properly wrap identifier parts with backticks and escape any existing backticks by doubling them when converting `SET CATALOG` commands to string literals. ### Why are the changes needed? A previous change in https://github.com/apache/spark/pull/53941 extended the `SET CATALOG` command to accept foldable expressions. As part of that change, identifiers quoted with backticks are resolved to `Literal("some-identifier")` with the backticks stripped. This behavior breaks `SET CATALOG` when catalog names contain special characters such as %, , -, $, #, or backticks. This fix wraps identifiers in explicit backticks and escapes any existing backticks, ensuring the catalog names are resolved correctly during analysis. ### Does this PR introduce _any_ user-facing change? Yes. Users can continue using `SET CATALOG` with catalog names that contain special characters when properly quoted with backticks: ```sql SET CATALOG `te%st-c$a#t` -- works with special characters SET CATALOG ``test`quote` -- works with backticks in the name ``` ### How was this patch tested? DataSourceV2SQLSuite: - SET CATALOG with special characters with backticks in identifier - SET CATALOG with backtick character in identifier ### Was this patch authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Sonnet 4.5 - claude-sonnet-4-5-20250929) Closes #54076 from tangrizzly/SPARK-55155-set-catalog-expression-fix-special-char. Authored-by: tangrizzly Signed-off-by: Daniel Tenedorio --- .../analysis/ResolveSetCatalogCommand.scala | 7 +++++-- .../sql/connector/DataSourceV2SQLSuite.scala | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/sql/core/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveSetCatalogCommand.scala b/sql/core/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveSetCatalogCommand.scala index 7f557fe625f5f..1e9c0dcfb2a44 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveSetCatalogCommand.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveSetCatalogCommand.scala @@ -20,6 +20,7 @@ package org.apache.spark.sql.catalyst.analysis import org.apache.spark.sql.catalyst.expressions.Literal import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan import org.apache.spark.sql.catalyst.rules.Rule +import org.apache.spark.sql.catalyst.util.QuotingUtils import org.apache.spark.sql.execution.command.SetCatalogCommand /** @@ -32,8 +33,10 @@ object ResolveSetCatalogCommand extends Rule[LogicalPlan] { case cmd @ SetCatalogCommand(expr) => val resolvedExpr = expr match { case UnresolvedAttribute(nameParts) => - // Convert `SET CATALOG foo` into Literal("foo"). - Literal(nameParts.mkString(".")) + // Convert `SET CATALOG foo` into Literal("`foo`"). + // Wrap each identifier part with backticks to handle + // special characters. + Literal(QuotingUtils.quoteNameParts(nameParts)) case other => // Other expressions (identifier(), CAST, CONCAT, etc.) are resolved diff --git a/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2SQLSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2SQLSuite.scala index 50b3bebaeb773..589e3ebffdefb 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2SQLSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2SQLSuite.scala @@ -3159,6 +3159,27 @@ class DataSourceV2SQLSuiteV1Filter queryContext = Array(ExpectedContext(fragment = "3.14", start = 12, stop = 15))) } + test("SET CATALOG with special characters with backticks in identifier") { + assertCurrentCatalog(SESSION_CATALOG_NAME) + + // Test catalog name with special characters like %, @, -, $, # + val catalogName = "te%s@t-c$a#t" + registerCatalog(catalogName, classOf[InMemoryCatalog]) + // Use backtick-quoted identifier + sql(s"SET CATALOG `$catalogName`") + assertCurrentCatalog(catalogName) + } + + test("SET CATALOG with backtick character in identifier") { + assertCurrentCatalog(SESSION_CATALOG_NAME) + + val catalogName = "test`quote" + registerCatalog(catalogName, classOf[InMemoryCatalog]) + // Use double backticks to escape the backtick in the name + sql("SET CATALOG `test``quote`") + assertCurrentCatalog(catalogName) + } + test("SPARK-35973: ShowCatalogs") { val schema = new StructType() .add("catalog", StringType, nullable = false) From 0a02d71adbe71a8af3c196249c7a486975a909b2 Mon Sep 17 00:00:00 2001 From: ericm-db Date: Wed, 25 Feb 2026 09:36:40 -0800 Subject: [PATCH 037/130] [SPARK-55601][SS] Hook StreamingSourceIdentifyingName into MicrobatchExecution for source naming ### What changes were proposed in this pull request? Move streamingSourceIdentifyingName from being passed explicitly through StreamingRelation constructors to being derived from DataSource itself via a lazy val, removing the overloaded StreamingRelation.apply and eliminating scattered Unassigned defaults at call sites. Pull the names from StreamingRelation and StreamingRelationV2 in MicroBatchExecution to key the OffsetMap by the source names during query execution ### Why are the changes needed? This is the last and final piece to allow for source naming ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Unit tests ### Was this patch authored or co-authored using generative AI tooling? No Closes #54373 from ericm-db/streaming-source-identifying-name. Authored-by: ericm-db Signed-off-by: Anish Shrigondekar --- .../StreamingSourceIdentifyingName.scala | 27 + .../catalyst/analysis/ResolveDataSource.scala | 17 +- .../execution/datasources/DataSource.scala | 7 +- .../datasources/DataSourceStrategy.scala | 2 +- .../streaming/checkpointing/OffsetSeq.scala | 6 +- .../runtime/MicroBatchExecution.scala | 67 ++- .../streaming/runtime/StreamingRelation.scala | 11 +- .../streaming/utils/StreamingUtils.scala | 46 ++ .../streaming/StreamRelationSuite.scala | 2 +- .../StreamingSourceIdentifyingNameSuite.scala | 6 +- .../test/StreamingQueryEvolutionSuite.scala | 176 ------ .../test/StreamingSourceEvolutionSuite.scala | 520 ++++++++++++++++++ 12 files changed, 667 insertions(+), 220 deletions(-) delete mode 100644 sql/core/src/test/scala/org/apache/spark/sql/streaming/test/StreamingQueryEvolutionSuite.scala create mode 100644 sql/core/src/test/scala/org/apache/spark/sql/streaming/test/StreamingSourceEvolutionSuite.scala diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/streaming/StreamingSourceIdentifyingName.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/streaming/StreamingSourceIdentifyingName.scala index b89aaf017b1da..8ac72e817811c 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/streaming/StreamingSourceIdentifyingName.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/streaming/StreamingSourceIdentifyingName.scala @@ -47,6 +47,33 @@ sealed trait StreamingSourceIdentifyingName { case FlowAssigned(name) => s"""name="$name"""" case Unassigned => "name=" } + + /** + * Extracts only user-provided names, filtering out flow-assigned or unassigned sources. + * Used when narrowing to explicitly user-specified names (e.g., when passing to DataSource). + * + * @return Option value set to the user-provided name if available, None otherwise + */ + def toUserProvided: Option[UserProvided] = this match { + case up: UserProvided => Some(up) + case _ => None + } + + /** + * Extracts the name string from named sources (UserProvided or FlowAssigned). + * Returns None for Unassigned sources. + * + * Useful for pattern matching when both UserProvided and FlowAssigned should be + * treated identically (e.g., when computing metadata paths or building sourceIdMap). + * + * @return Option value set to the source name (user-provided or flow-assigned) if available, + * None otherwise + */ + def nameOpt: Option[String] = this match { + case UserProvided(name) => Some(name) + case FlowAssigned(name) => Some(name) + case Unassigned => None + } } /** diff --git a/sql/core/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveDataSource.scala b/sql/core/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveDataSource.scala index 35ff39ce82682..2f139393ade38 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveDataSource.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveDataSource.scala @@ -24,7 +24,7 @@ import scala.jdk.CollectionConverters._ import org.apache.spark.sql.catalyst.analysis.NamedStreamingRelation import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, UnresolvedDataSource} import org.apache.spark.sql.catalyst.rules.Rule -import org.apache.spark.sql.catalyst.streaming.{StreamingRelationV2, Unassigned} +import org.apache.spark.sql.catalyst.streaming.StreamingRelationV2 import org.apache.spark.sql.catalyst.types.DataTypeUtils.toAttributes import org.apache.spark.sql.catalyst.util.CaseInsensitiveMap import org.apache.spark.sql.classic.SparkSession @@ -84,10 +84,11 @@ class ResolveDataSource(sparkSession: SparkSession) extends Rule[LogicalPlan] { sparkSession, userSpecifiedSchema = userSpecifiedSchema, className = source, - options = optionsWithPath.originalMap) + options = optionsWithPath.originalMap, + userSpecifiedStreamingSourceName = sourceIdentifyingName.toUserProvided) val v1Relation = ds match { case _: StreamSourceProvider => - Some(StreamingRelation(v1DataSource, sourceIdentifyingName)) + Some(StreamingRelation(v1DataSource)) case _ => None } ds match { @@ -112,16 +113,16 @@ class ResolveDataSource(sparkSession: SparkSession) extends Rule[LogicalPlan] { StreamingRelationV2( Some(provider), source, table, dsOptions, toAttributes(table.columns.asSchema), None, None, v1Relation, - sourceIdentifyingName) + v1DataSource.streamingSourceIdentifyingName) // fallback to v1 // TODO (SPARK-27483): we should move this fallback logic to an analyzer rule. - case _ => StreamingRelation(v1DataSource, sourceIdentifyingName) + case _ => StreamingRelation(v1DataSource) } case _ => // Code path for data source v1. - StreamingRelation(v1DataSource, sourceIdentifyingName) + StreamingRelation(v1DataSource) } case UnresolvedDataSource(source, userSpecifiedSchema, extraOptions, true, paths) => @@ -148,7 +149,7 @@ class ResolveDataSource(sparkSession: SparkSession) extends Rule[LogicalPlan] { options = optionsWithPath.originalMap) val v1Relation = ds match { case _: StreamSourceProvider => - Some(StreamingRelation(v1DataSource, Unassigned)) + Some(StreamingRelation(v1DataSource)) case _ => None } ds match { @@ -173,7 +174,7 @@ class ResolveDataSource(sparkSession: SparkSession) extends Rule[LogicalPlan] { StreamingRelationV2( Some(provider), source, table, dsOptions, toAttributes(table.columns.asSchema), None, None, v1Relation, - Unassigned) + v1DataSource.streamingSourceIdentifyingName) // fallback to v1 // TODO (SPARK-27483): we should move this fallback logic to an analyzer rule. diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSource.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSource.scala index 0c234e3fcf189..d2ec3f7ff486b 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSource.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSource.scala @@ -34,7 +34,7 @@ import org.apache.spark.sql.catalyst.DataSourceOptions import org.apache.spark.sql.catalyst.analysis.UnresolvedAttribute import org.apache.spark.sql.catalyst.catalog.{BucketSpec, CatalogStorageFormat, CatalogTable, CatalogUtils} import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan -import org.apache.spark.sql.catalyst.streaming.StreamingSourceIdentifyingName +import org.apache.spark.sql.catalyst.streaming.{StreamingSourceIdentifyingName, Unassigned, UserProvided} import org.apache.spark.sql.catalyst.util.{CaseInsensitiveMap, TypeUtils} import org.apache.spark.sql.classic.ClassicConversions.castToImpl import org.apache.spark.sql.classic.Dataset @@ -103,13 +103,16 @@ case class DataSource( bucketSpec: Option[BucketSpec] = None, options: Map[String, String] = Map.empty, catalogTable: Option[CatalogTable] = None, - userSpecifiedStreamingSourceName: Option[StreamingSourceIdentifyingName] = None) + userSpecifiedStreamingSourceName: Option[UserProvided] = None) extends SessionStateHelper with Logging { case class SourceInfo(name: String, schema: StructType, partitionColumns: Seq[String]) private val conf: SQLConf = getSqlConf(sparkSession) + lazy val streamingSourceIdentifyingName: StreamingSourceIdentifyingName = + userSpecifiedStreamingSourceName.getOrElse(Unassigned) + lazy val providingClass: Class[_] = { val cls = DataSource.lookupDataSource(className, conf) // `providingClass` is used for resolving data source relation for catalog tables. diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSourceStrategy.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSourceStrategy.scala index 220b0b8a63013..63782c753696c 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSourceStrategy.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/DataSourceStrategy.scala @@ -305,7 +305,7 @@ class FindDataSourceTable(sparkSession: SparkSession) extends Rule[LogicalPlan] userSpecifiedSchema = Some(table.schema), options = dsOptions, catalogTable = Some(table), - userSpecifiedStreamingSourceName = Some(sourceIdentifyingName)) + userSpecifiedStreamingSourceName = sourceIdentifyingName.toUserProvided) StreamingRelation(dataSource) } diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/checkpointing/OffsetSeq.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/checkpointing/OffsetSeq.scala index dff09c736a835..bf2278b814922 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/checkpointing/OffsetSeq.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/checkpointing/OffsetSeq.scala @@ -203,7 +203,8 @@ object OffsetSeqMetadata extends Logging { STATE_STORE_ROCKSDB_FORMAT_VERSION, STATE_STORE_ROCKSDB_MERGE_OPERATOR_VERSION, STATEFUL_OPERATOR_USE_STRICT_DISTRIBUTION, PRUNE_FILTERS_CAN_PRUNE_STREAMING_SUBPLAN, STREAMING_STATE_STORE_ENCODING_FORMAT, - STATE_STORE_ROW_CHECKSUM_ENABLED, PROTOBUF_EXTENSIONS_SUPPORT_ENABLED + STATE_STORE_ROW_CHECKSUM_ENABLED, PROTOBUF_EXTENSIONS_SUPPORT_ENABLED, + ENABLE_STREAMING_SOURCE_EVOLUTION ) /** @@ -252,7 +253,8 @@ object OffsetSeqMetadata extends Logging { STREAMING_STATE_STORE_ENCODING_FORMAT.key -> "unsaferow", STATE_STORE_ROW_CHECKSUM_ENABLED.key -> "false", STATE_STORE_ROCKSDB_MERGE_OPERATOR_VERSION.key -> "1", - PROTOBUF_EXTENSIONS_SUPPORT_ENABLED.key -> "false" + PROTOBUF_EXTENSIONS_SUPPORT_ENABLED.key -> "false", + ENABLE_STREAMING_SOURCE_EVOLUTION.key -> "false" ) def readValue[T](metadataLog: OffsetSeqMetadataBase, confKey: ConfigEntry[T]): String = { diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/MicroBatchExecution.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/MicroBatchExecution.scala index a4f50993f64ba..35a658d350ab5 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/MicroBatchExecution.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/MicroBatchExecution.scala @@ -17,6 +17,8 @@ package org.apache.spark.sql.execution.streaming.runtime +import java.util.concurrent.atomic.AtomicLong + import scala.collection.mutable.{Map => MutableMap} import scala.collection.mutable import scala.jdk.CollectionConverters._ @@ -30,7 +32,7 @@ import org.apache.spark.internal.LogKeys._ import org.apache.spark.sql.catalyst.encoders.ExpressionEncoder import org.apache.spark.sql.catalyst.expressions.{Alias, Attribute, CurrentBatchTimestamp, CurrentDate, CurrentTimestamp, FileSourceMetadataAttribute, LocalTimestamp} import org.apache.spark.sql.catalyst.plans.logical.{Aggregate, Deduplicate, DeduplicateWithinWatermark, Distinct, FlatMapGroupsInPandasWithState, FlatMapGroupsWithState, GlobalLimit, Join, LeafNode, LocalRelation, LogicalPlan, Project, StreamSourceAwareLogicalPlan, TransformWithState, TransformWithStateInPySpark} -import org.apache.spark.sql.catalyst.streaming.{StreamingRelationV2, WriteToStream} +import org.apache.spark.sql.catalyst.streaming.{StreamingRelationV2, Unassigned, WriteToStream} import org.apache.spark.sql.catalyst.trees.TreePattern.CURRENT_LIKE import org.apache.spark.sql.catalyst.util.truncatedString import org.apache.spark.sql.classic.{Dataset, SparkSession} @@ -48,6 +50,7 @@ import org.apache.spark.sql.execution.streaming.runtime.AcceptsLatestSeenOffsetH import org.apache.spark.sql.execution.streaming.runtime.StreamingCheckpointConstants.{DIR_NAME_COMMITS, DIR_NAME_OFFSETS, DIR_NAME_STATE} import org.apache.spark.sql.execution.streaming.sources.{ForeachBatchSink, WriteToMicroBatchDataSource, WriteToMicroBatchDataSourceV1} import org.apache.spark.sql.execution.streaming.state.{OfflineStateRepartitionUtils, StateSchemaBroadcast, StateStoreErrors} +import org.apache.spark.sql.execution.streaming.utils.StreamingUtils import org.apache.spark.sql.internal.SQLConf import org.apache.spark.sql.internal.connector.PartitionOffsetWithIndex import org.apache.spark.sql.streaming.Trigger @@ -168,7 +171,7 @@ class MicroBatchExecution( assert(queryExecutionThread eq Thread.currentThread, "logicalPlan must be initialized in QueryExecutionThread " + s"but the current thread was ${Thread.currentThread}") - var nextSourceId = 0L + val nextSourceId = new AtomicLong(0L) val toExecutionRelationMap = MutableMap[StreamingRelation, StreamingExecutionRelation]() val v2ToExecutionRelationMap = MutableMap[StreamingRelationV2, StreamingExecutionRelation]() val v2ToRelationMap = MutableMap[StreamingRelationV2, StreamingDataSourceV2ScanRelation]() @@ -183,15 +186,24 @@ class MicroBatchExecution( val disabledSources = Utils.stringToSeq(sparkSession.sessionState.conf.disabledV2StreamingMicroBatchReaders) + // Read the source evolution enforcement from the last written offset log entry. If no entries + // are found, use the session config value. + val enforceNamed = offsetLog.getLatest().flatMap { case (_, offsetSeq) => + offsetSeq.metadataOpt.flatMap { metadata => + OffsetSeqMetadata.readValueOpt(metadata, SQLConf.ENABLE_STREAMING_SOURCE_EVOLUTION) + .map(_.toBoolean) + } + }.getOrElse(sparkSessionForStream.sessionState.conf.enableStreamingSourceEvolution) + import org.apache.spark.sql.execution.datasources.v2.DataSourceV2Implicits._ val _logicalPlan = analyzedPlan.transform { case streamingRelation @ StreamingRelation( dataSourceV1, sourceName, output, sourceIdentifyingName) => toExecutionRelationMap.getOrElseUpdate(streamingRelation, { // Materialize source to avoid creating it in every batch - val metadataPath = s"$resolvedCheckpointRoot/sources/$nextSourceId" + val metadataPath = StreamingUtils.getMetadataPath( + sourceIdentifyingName, nextSourceId, resolvedCheckpointRoot) val source = dataSourceV1.createSource(metadataPath) - nextSourceId += 1 logInfo(log"Using Source [${MDC(LogKeys.STREAMING_SOURCE, source)}] " + log"from DataSourceV1 named '${MDC(LogKeys.STREAMING_DATA_SOURCE_NAME, sourceName)}' " + log"[${MDC(LogKeys.STREAMING_DATA_SOURCE_DESCRIPTION, dataSourceV1)}]") @@ -206,8 +218,8 @@ class MicroBatchExecution( if (!v2Disabled && table.supports(TableCapability.MICRO_BATCH_READ)) { v2ToRelationMap.getOrElseUpdate(s, { // Materialize source to avoid creating it in every batch - val metadataPath = s"$resolvedCheckpointRoot/sources/$nextSourceId" - nextSourceId += 1 + val metadataPath = StreamingUtils.getMetadataPath( + sourceIdentifyingName, nextSourceId, resolvedCheckpointRoot) logInfo(log"Reading table [${MDC(LogKeys.STREAMING_TABLE, table)}] " + log"from DataSourceV2 named '${MDC(LogKeys.STREAMING_DATA_SOURCE_NAME, srcName)}' " + log"${MDC(LogKeys.STREAMING_DATA_SOURCE_DESCRIPTION, dsStr)}") @@ -224,7 +236,8 @@ class MicroBatchExecution( trigger match { case RealTimeTrigger(duration) => Some(duration) case _ => None - } + }, + sourceIdentifyingName ) StreamingDataSourceV2ScanRelation(relation, scan, output, stream) }) @@ -234,10 +247,10 @@ class MicroBatchExecution( } else { v2ToExecutionRelationMap.getOrElseUpdate(s, { // Materialize source to avoid creating it in every batch - val metadataPath = s"$resolvedCheckpointRoot/sources/$nextSourceId" + val metadataPath = StreamingUtils.getMetadataPath( + sourceIdentifyingName, nextSourceId, resolvedCheckpointRoot) val source = v1.get.asInstanceOf[StreamingRelation].dataSource.createSource(metadataPath) - nextSourceId += 1 logInfo(log"Using Source [${MDC(LogKeys.STREAMING_SOURCE, source)}] from " + log"DataSourceV2 named '${MDC(LogKeys.STREAMING_DATA_SOURCE_NAME, srcName)}' " + log"${MDC(LogKeys.STREAMING_DATA_SOURCE_DESCRIPTION, dsStr)}") @@ -247,17 +260,37 @@ class MicroBatchExecution( }) } } - sources = _logicalPlan.collect { + + // Extract sources and their sourceIdentifyingName for sourceIdMap mapping + val sourcesWithNames = _logicalPlan.collect { // v1 source - case s: StreamingExecutionRelation => s.source + case s: StreamingExecutionRelation => (s.source, s.sourceIdentifyingName) // v2 source - case r: StreamingDataSourceV2ScanRelation => r.stream + case r: StreamingDataSourceV2ScanRelation => (r.stream, r.relation.sourceIdentifyingName) + } + sources = sourcesWithNames.map(_._1) + + if (enforceNamed) { + // When enforcement is enabled, all sources should be named after validation in analysis. + // This assertion ensures that the validation in NameStreamingSources worked correctly. + assert(sourcesWithNames.forall(s => s._2 != Unassigned), + "All sources should be named at this point - validation should have happened in analysis") + + // Create source ID mapping using names (for OffsetMap format) + sourceIdMap = sourcesWithNames.map { case (source, sourceIdentifyingName) => + sourceIdentifyingName.nameOpt match { + case Some(name) => name -> source + case None => + throw new IllegalStateException( + "Unassigned sources should not exist when enforcement is enabled") + } + }.toMap + } else { + // When enforcement is disabled, use positional indices (backward compatibility) + sourceIdMap = sources.zipWithIndex.map { + case (source, index) => index.toString -> source + }.toMap } - - // Create source ID mapping for OffsetMap support - sourceIdMap = sources.zipWithIndex.map { - case (source, index) => index.toString -> source - }.toMap // Inform the source if it is in real time mode if (trigger.isInstanceOf[RealTimeTrigger]) { diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/StreamingRelation.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/StreamingRelation.scala index 232f3475bb1bd..efa65bc5ead49 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/StreamingRelation.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/StreamingRelation.scala @@ -36,18 +36,9 @@ import org.apache.spark.sql.sources.SupportsStreamSourceMetadataColumns object StreamingRelation { def apply(dataSource: DataSource): StreamingRelation = { // Extract source identifying name from DataSource for stable checkpoints - val sourceIdentifyingName = dataSource.userSpecifiedStreamingSourceName.getOrElse(Unassigned) StreamingRelation( dataSource, dataSource.sourceInfo.name, toAttributes(dataSource.sourceInfo.schema), - sourceIdentifyingName) - } - - def apply( - dataSource: DataSource, - sourceIdentifyingName: StreamingSourceIdentifyingName): StreamingRelation = { - StreamingRelation( - dataSource, dataSource.sourceInfo.name, toAttributes(dataSource.sourceInfo.schema), - sourceIdentifyingName) + dataSource.streamingSourceIdentifyingName) } } diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/utils/StreamingUtils.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/utils/StreamingUtils.scala index d2654ac943b2c..8dfc1fd23b57d 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/utils/StreamingUtils.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/utils/StreamingUtils.scala @@ -16,13 +16,59 @@ */ package org.apache.spark.sql.execution.streaming.utils +import java.util.concurrent.atomic.AtomicLong + import org.apache.hadoop.conf.Configuration import org.apache.hadoop.fs.Path +import org.apache.spark.sql.catalyst.streaming.StreamingSourceIdentifyingName + object StreamingUtils { + /** + * Resolves a checkpoint location to a fully qualified path. + * + * Converts relative or unqualified paths to fully qualified paths using the + * file system's URI and working directory. + * + * @param hadoopConf Hadoop configuration to access the file system + * @param checkpointLocation The checkpoint location path (may be relative or unqualified) + * @return Fully qualified checkpoint location URI as a string + */ def resolvedCheckpointLocation(hadoopConf: Configuration, checkpointLocation: String): String = { val checkpointPath = new Path(checkpointLocation) val fs = checkpointPath.getFileSystem(hadoopConf) checkpointPath.makeQualified(fs.getUri, fs.getWorkingDirectory).toUri.toString } + + /** + * Computes the metadata path for a streaming source based on its identifying name. + * + * Named sources (UserProvided/FlowAssigned) use stable name-based paths, enabling + * source evolution (reordering, adding, or removing sources without breaking state). + * Unassigned sources use sequential IDs for backward compatibility. + * + * Examples: + * - UserProvided("mySource") => "$checkpointRoot/sources/mySource" + * - FlowAssigned("source_1") => "$checkpointRoot/sources/source_1" + * - Unassigned => "$checkpointRoot/sources/0" (increments nextSourceId) + * + * @param sourceIdentifyingName The source's identifying name + * (UserProvided, FlowAssigned, or Unassigned) + * @param nextSourceId AtomicLong tracking the next positional source ID for Unassigned sources + * @param resolvedCheckpointRoot The resolved checkpoint root path + * @return The computed metadata path string + */ + def getMetadataPath( + sourceIdentifyingName: StreamingSourceIdentifyingName, + nextSourceId: AtomicLong, + resolvedCheckpointRoot: String): String = { + sourceIdentifyingName.nameOpt match { + case Some(name) => + // User-provided and flow-assigned names use named paths + s"$resolvedCheckpointRoot/sources/$name" + case None => + // Unassigned sources get sequential IDs assigned here + s"$resolvedCheckpointRoot/sources/${nextSourceId.getAndIncrement()}" + } + } } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/StreamRelationSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/StreamRelationSuite.scala index 599a48c642085..dc8da2d5a6286 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/StreamRelationSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/StreamRelationSuite.scala @@ -146,7 +146,7 @@ class StreamRelationSuite extends SharedSparkSession with AnalysisTest { ), userSpecifiedSchema = Option(catalogTable.schema), catalogTable = Option(catalogTable), - userSpecifiedStreamingSourceName = Some(Unassigned) + userSpecifiedStreamingSourceName = None ), sourceName = s"FileSource[${catalogTable.location.toString}]", output = Seq(idAttr) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/streaming/StreamingSourceIdentifyingNameSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/streaming/StreamingSourceIdentifyingNameSuite.scala index caf6c14c8000c..c89895035c91a 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/streaming/StreamingSourceIdentifyingNameSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/streaming/StreamingSourceIdentifyingNameSuite.scala @@ -43,10 +43,10 @@ class StreamingSourceIdentifyingNameSuite extends SharedSparkSession { assert(streamingRelation.get.sourceIdentifyingName == Unassigned, s"Expected Unassigned but got ${streamingRelation.get.sourceIdentifyingName}") - // Verify the DataSource has the sourceIdentifyingName set + // Verify the DataSource has no user-specified source name (None means no user-provided name) val dsSourceName = streamingRelation.get.dataSource.userSpecifiedStreamingSourceName - assert(dsSourceName == Some(Unassigned), - s"Expected Some(Unassigned) but got $dsSourceName") + assert(dsSourceName.isEmpty, + s"Expected None but got $dsSourceName") } } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/streaming/test/StreamingQueryEvolutionSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/streaming/test/StreamingQueryEvolutionSuite.scala deleted file mode 100644 index 973e2f75439eb..0000000000000 --- a/sql/core/src/test/scala/org/apache/spark/sql/streaming/test/StreamingQueryEvolutionSuite.scala +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.spark.sql.streaming.test - -import org.scalatest.Tag - -import org.apache.spark.sql._ -import org.apache.spark.sql.internal.SQLConf -import org.apache.spark.sql.streaming.StreamTest - -/** - * Test suite for streaming source naming and validation. - * Tests cover the naming API, validation rules, and resolution pipeline. - */ -class StreamingQueryEvolutionSuite extends StreamTest { - - // ==================== - // Name Validation Tests - // ==================== - - testWithSourceEvolution("invalid source name - contains hyphen") { - checkError( - exception = intercept[AnalysisException] { - spark.readStream - .format("org.apache.spark.sql.streaming.test") - .name("my-source") - .load() - }, - condition = "STREAMING_QUERY_EVOLUTION_ERROR.INVALID_SOURCE_NAME", - parameters = Map("sourceName" -> "my-source")) - } - - testWithSourceEvolution("invalid source name - contains space") { - checkError( - exception = intercept[AnalysisException] { - spark.readStream - .format("org.apache.spark.sql.streaming.test") - .name("my source") - .load() - }, - condition = "STREAMING_QUERY_EVOLUTION_ERROR.INVALID_SOURCE_NAME", - parameters = Map("sourceName" -> "my source")) - } - - testWithSourceEvolution("invalid source name - contains dot") { - checkError( - exception = intercept[AnalysisException] { - spark.readStream - .format("org.apache.spark.sql.streaming.test") - .name("my.source") - .load() - }, - condition = "STREAMING_QUERY_EVOLUTION_ERROR.INVALID_SOURCE_NAME", - parameters = Map("sourceName" -> "my.source")) - } - - testWithSourceEvolution("invalid source name - contains special characters") { - checkError( - exception = intercept[AnalysisException] { - spark.readStream - .format("org.apache.spark.sql.streaming.test") - .name("my.source@123") - .load() - }, - condition = "STREAMING_QUERY_EVOLUTION_ERROR.INVALID_SOURCE_NAME", - parameters = Map("sourceName" -> "my.source@123")) - } - - testWithSourceEvolution("valid source names - various patterns") { - // Test that valid names work correctly - Seq("mySource", "my_source", "MySource123", "_private", "source_123_test", "123source") - .foreach { name => - val df = spark.readStream - .format("org.apache.spark.sql.streaming.test") - .name(name) - .load() - assert(df.isStreaming, s"DataFrame should be streaming for name: $name") - } - } - - testWithSourceEvolution("method chaining - name() returns reader for chaining") { - val df = spark.readStream - .format("org.apache.spark.sql.streaming.test") - .name("my_source") - .option("opt1", "value1") - .load() - - assert(df.isStreaming, "DataFrame should be streaming") - } - - // ========================== - // Duplicate Detection Tests - // ========================== - - testWithSourceEvolution("duplicate source names - rejected when starting stream") { - withTempDir { checkpointDir => - val df1 = spark.readStream - .format("org.apache.spark.sql.streaming.test") - .name("duplicate_name") - .load() - - val df2 = spark.readStream - .format("org.apache.spark.sql.streaming.test") - .name("duplicate_name") // Same name - should fail - .load() - - checkError( - exception = intercept[AnalysisException] { - df1.union(df2).writeStream - .format("org.apache.spark.sql.streaming.test") - .option("checkpointLocation", checkpointDir.getCanonicalPath) - .start() - }, - condition = "STREAMING_QUERY_EVOLUTION_ERROR.DUPLICATE_SOURCE_NAMES", - parameters = Map("names" -> "'duplicate_name'")) - } - } - - testWithSourceEvolution("enforcement enabled - unnamed source rejected") { - checkError( - exception = intercept[AnalysisException] { - spark.readStream - .format("org.apache.spark.sql.streaming.test") - .load() // Unnamed - throws error at load() time - }, - condition = "STREAMING_QUERY_EVOLUTION_ERROR.UNNAMED_STREAMING_SOURCES_WITH_ENFORCEMENT", - parameters = Map("sourceInfo" -> ".*"), - matchPVals = true) - } - - testWithSourceEvolution("enforcement enabled - all sources named succeeds") { - val df1 = spark.readStream - .format("org.apache.spark.sql.streaming.test") - .name("alpha") - .load() - - val df2 = spark.readStream - .format("org.apache.spark.sql.streaming.test") - .name("beta") - .load() - - // Should not throw - all sources are named - val union = df1.union(df2) - assert(union.isStreaming, "Union should be streaming") - } - - // ============== - // Helper Methods - // ============== - - /** - * Helper method to run tests with source evolution enabled. - */ - def testWithSourceEvolution(testName: String, testTags: Tag*)(testBody: => Any): Unit = { - test(testName, testTags: _*) { - withSQLConf(SQLConf.ENABLE_STREAMING_SOURCE_EVOLUTION.key -> "true") { - testBody - } - } - } -} diff --git a/sql/core/src/test/scala/org/apache/spark/sql/streaming/test/StreamingSourceEvolutionSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/streaming/test/StreamingSourceEvolutionSuite.scala new file mode 100644 index 0000000000000..ec919f1f12429 --- /dev/null +++ b/sql/core/src/test/scala/org/apache/spark/sql/streaming/test/StreamingSourceEvolutionSuite.scala @@ -0,0 +1,520 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.spark.sql.streaming.test + +import scala.concurrent.duration._ + +import org.apache.hadoop.fs.Path +import org.mockito.ArgumentMatchers.{any, eq => meq} +import org.mockito.Mockito._ +import org.scalatest.{BeforeAndAfterEach, Tag} + +import org.apache.spark.sql._ +import org.apache.spark.sql.internal.SQLConf +import org.apache.spark.sql.streaming.StreamTest +import org.apache.spark.sql.streaming.Trigger._ +import org.apache.spark.util.Utils + +/** + * Test suite for streaming source naming and validation. + * Tests cover the naming API, validation rules, and resolution pipeline. + */ +class StreamingSourceEvolutionSuite extends StreamTest with BeforeAndAfterEach { + + private def newMetadataDir = + Utils.createTempDir(namePrefix = "streaming.metadata").getCanonicalPath + + override def afterEach(): Unit = { + spark.streams.active.foreach(_.stop()) + super.afterEach() + } + + /** + * Helper to verify that a source was created with the expected metadata path. + * @param checkpointLocation the checkpoint location path + * @param sourcePath the expected source path (e.g., "source1" or "0") + * @param mode mockito verification mode (default: times(1)) + */ + private def verifySourcePath( + checkpointLocation: Path, + sourcePath: String, + mode: org.mockito.verification.VerificationMode = times(1)): Unit = { + verify(LastOptions.mockStreamSourceProvider, mode).createSource( + any(), + meq(s"${new Path(makeQualifiedPath( + checkpointLocation.toString)).toString}/sources/$sourcePath"), + meq(None), + meq("org.apache.spark.sql.streaming.test"), + meq(Map.empty)) + } + + // ==================== + // Name Validation Tests + // ==================== + + testWithSourceEvolution("invalid source name - contains hyphen") { + checkError( + exception = intercept[AnalysisException] { + spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("my-source") + .load() + }, + condition = "STREAMING_QUERY_EVOLUTION_ERROR.INVALID_SOURCE_NAME", + parameters = Map("sourceName" -> "my-source")) + } + + testWithSourceEvolution("invalid source name - contains space") { + checkError( + exception = intercept[AnalysisException] { + spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("my source") + .load() + }, + condition = "STREAMING_QUERY_EVOLUTION_ERROR.INVALID_SOURCE_NAME", + parameters = Map("sourceName" -> "my source")) + } + + testWithSourceEvolution("invalid source name - contains dot") { + checkError( + exception = intercept[AnalysisException] { + spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("my.source") + .load() + }, + condition = "STREAMING_QUERY_EVOLUTION_ERROR.INVALID_SOURCE_NAME", + parameters = Map("sourceName" -> "my.source")) + } + + testWithSourceEvolution("invalid source name - contains special characters") { + checkError( + exception = intercept[AnalysisException] { + spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("my.source@123") + .load() + }, + condition = "STREAMING_QUERY_EVOLUTION_ERROR.INVALID_SOURCE_NAME", + parameters = Map("sourceName" -> "my.source@123")) + } + + testWithSourceEvolution("valid source names - various patterns") { + // Test that valid names work correctly + Seq("mySource", "my_source", "MySource123", "_private", "source_123_test", "123source") + .foreach { name => + val df = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name(name) + .load() + assert(df.isStreaming, s"DataFrame should be streaming for name: $name") + } + } + + testWithSourceEvolution("method chaining - name() returns reader for chaining") { + val df = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("my_source") + .option("opt1", "value1") + .load() + + assert(df.isStreaming, "DataFrame should be streaming") + } + + // ========================== + // Duplicate Detection Tests + // ========================== + + testWithSourceEvolution("duplicate source names - rejected when starting stream") { + withTempDir { checkpointDir => + val df1 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("duplicate_name") + .load() + + val df2 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("duplicate_name") // Same name - should fail + .load() + + checkError( + exception = intercept[AnalysisException] { + df1.union(df2).writeStream + .format("org.apache.spark.sql.streaming.test") + .option("checkpointLocation", checkpointDir.getCanonicalPath) + .start() + }, + condition = "STREAMING_QUERY_EVOLUTION_ERROR.DUPLICATE_SOURCE_NAMES", + parameters = Map("names" -> "'duplicate_name'")) + } + } + + testWithSourceEvolution("enforcement enabled - unnamed source rejected") { + checkError( + exception = intercept[AnalysisException] { + spark.readStream + .format("org.apache.spark.sql.streaming.test") + .load() // Unnamed - throws error at load() time + }, + condition = "STREAMING_QUERY_EVOLUTION_ERROR.UNNAMED_STREAMING_SOURCES_WITH_ENFORCEMENT", + parameters = Map("sourceInfo" -> ".*"), + matchPVals = true) + } + + testWithSourceEvolution("enforcement enabled - all sources named succeeds") { + val df1 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("alpha") + .load() + + val df2 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("beta") + .load() + + // Should not throw - all sources are named + val union = df1.union(df2) + assert(union.isStreaming, "Union should be streaming") + } + + test("without enforcement - naming sources throws error") { + withSQLConf(SQLConf.ENABLE_STREAMING_SOURCE_EVOLUTION.key -> "false") { + checkError( + exception = intercept[AnalysisException] { + spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("mySource") + .load() + }, + condition = "STREAMING_QUERY_EVOLUTION_ERROR.SOURCE_NAMING_NOT_SUPPORTED", + parameters = Map("name" -> "mySource")) + } + } + + // ======================= + // Metadata Path Tests + // ======================= + + testWithSourceEvolution("named sources - metadata path uses source name") { + LastOptions.clear() + + val checkpointLocation = new Path(newMetadataDir) + + val df1 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source1") + .load() + + val df2 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source2") + .load() + + val q = df1.union(df2).writeStream + .format("org.apache.spark.sql.streaming.test") + .option("checkpointLocation", checkpointLocation.toString) + .trigger(ProcessingTime(10.seconds)) + .start() + q.processAllAvailable() + q.stop() + + verifySourcePath(checkpointLocation, "source1") + verifySourcePath(checkpointLocation, "source2") + } + + test("unnamed sources use positional IDs for metadata path") { + withSQLConf(SQLConf.ENABLE_STREAMING_SOURCE_EVOLUTION.key -> "false") { + LastOptions.clear() + + val checkpointLocation = new Path(newMetadataDir) + + val df1 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .load() + + val df2 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .load() + + val q = df1.union(df2).writeStream + .format("org.apache.spark.sql.streaming.test") + .option("checkpointLocation", checkpointLocation.toString) + .trigger(ProcessingTime(10.seconds)) + .start() + q.processAllAvailable() + q.stop() + + // Without naming, sources get sequential IDs (Unassigned -> 0, 1, ...) + verifySourcePath(checkpointLocation, "0") + verifySourcePath(checkpointLocation, "1") + } + } + + // ======================== + // Source Evolution Tests + // ======================== + + testWithSourceEvolution("source evolution - reorder sources with named sources") { + LastOptions.clear() + + val checkpointLocation = new Path(newMetadataDir) + + // First query: source1 then source2 + val df1a = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source1") + .load() + + val df2a = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source2") + .load() + + val q1 = df1a.union(df2a).writeStream + .format("org.apache.spark.sql.streaming.test") + .option("checkpointLocation", checkpointLocation.toString) + .trigger(ProcessingTime(10.seconds)) + .start() + q1.processAllAvailable() + q1.stop() + + LastOptions.clear() + + // Second query: source2 then source1 (reordered) - should still work + val df1b = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source1") + .load() + + val df2b = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source2") + .load() + + val q2 = df2b.union(df1b).writeStream // Note: reversed order + .format("org.apache.spark.sql.streaming.test") + .option("checkpointLocation", checkpointLocation.toString) + .trigger(ProcessingTime(10.seconds)) + .start() + q2.processAllAvailable() + q2.stop() + + // Both sources should still use their named paths + verifySourcePath(checkpointLocation, "source1", atLeastOnce()) + verifySourcePath(checkpointLocation, "source2", atLeastOnce()) + } + + testWithSourceEvolution("source evolution - add new source with named sources") { + LastOptions.clear() + + val checkpointLocation = new Path(newMetadataDir) + + // First query: only source1 + val df1 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source1") + .load() + + val q1 = df1.writeStream + .format("org.apache.spark.sql.streaming.test") + .option("checkpointLocation", checkpointLocation.toString) + .trigger(ProcessingTime(10.seconds)) + .start() + q1.processAllAvailable() + q1.stop() + + LastOptions.clear() + + // Second query: add source2 + val df1b = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source1") + .load() + + val df2 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source2") + .load() + + val q2 = df1b.union(df2).writeStream + .format("org.apache.spark.sql.streaming.test") + .option("checkpointLocation", checkpointLocation.toString) + .trigger(ProcessingTime(10.seconds)) + .start() + q2.processAllAvailable() + q2.stop() + + // Both sources should have been created + verifySourcePath(checkpointLocation, "source1", atLeastOnce()) + verifySourcePath(checkpointLocation, "source2") + } + + testWithSourceEvolution("named sources enforcement uses V2 offset log format") { + LastOptions.clear() + + val checkpointLocation = new Path(newMetadataDir) + + val df1 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source1") + .load() + + val df2 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source2") + .load() + + val q = df1.union(df2).writeStream + .format("org.apache.spark.sql.streaming.test") + .option("checkpointLocation", checkpointLocation.toString) + .trigger(ProcessingTime(10.seconds)) + .start() + q.processAllAvailable() + q.stop() + + import org.apache.spark.sql.execution.streaming.checkpointing.{OffsetMap, OffsetSeqLog} + val offsetLog = new OffsetSeqLog(spark, + makeQualifiedPath(checkpointLocation.toString).toString + "/offsets") + val offsetSeq = offsetLog.get(0) + assert(offsetSeq.isDefined, "Offset log should have batch 0") + assert(offsetSeq.get.isInstanceOf[OffsetMap], + s"Expected OffsetMap but got ${offsetSeq.get.getClass.getSimpleName}") + } + + testWithSourceEvolution("names preserved through union operations") { + LastOptions.clear() + + val checkpointLocation = new Path(newMetadataDir) + + val df1 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("alpha") + .load() + + val df2 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("beta") + .load() + + val df3 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("gamma") + .load() + + // Complex union: (alpha union beta) union gamma + val q = df1.union(df2).union(df3).writeStream + .format("org.apache.spark.sql.streaming.test") + .option("checkpointLocation", checkpointLocation.toString) + .trigger(ProcessingTime(10.seconds)) + .start() + q.processAllAvailable() + q.stop() + + // All three sources should use their named paths + verifySourcePath(checkpointLocation, "alpha") + verifySourcePath(checkpointLocation, "beta") + verifySourcePath(checkpointLocation, "gamma") + } + + testWithSourceEvolution("enforcement config is persisted in offset metadata") { + LastOptions.clear() + + val checkpointLocation = new Path(newMetadataDir) + + // Start query with enforcement enabled + val df1 = spark.readStream + .format("org.apache.spark.sql.streaming.test") + .name("source1") + .load() + + val q1 = df1.writeStream + .format("org.apache.spark.sql.streaming.test") + .option("checkpointLocation", checkpointLocation.toString) + .trigger(ProcessingTime(10.seconds)) + .start() + q1.processAllAvailable() + q1.stop() + + // Verify config was persisted in offset metadata + import org.apache.spark.sql.execution.streaming.checkpointing.OffsetSeqLog + val offsetLog = new OffsetSeqLog(spark, + makeQualifiedPath(checkpointLocation.toString).toString + "/offsets") + val offsetSeq = offsetLog.get(0) + assert(offsetSeq.isDefined, "Offset log should have batch 0") + assert(offsetSeq.get.metadataOpt.isDefined, "Offset metadata should be present") + assert(offsetSeq.get.metadataOpt.get.conf.contains( + SQLConf.ENABLE_STREAMING_SOURCE_EVOLUTION.key), + "ENABLE_STREAMING_SOURCE_EVOLUTION should be in offset metadata") + assert(offsetSeq.get.metadataOpt.get.conf( + SQLConf.ENABLE_STREAMING_SOURCE_EVOLUTION.key) == "true", + "ENABLE_STREAMING_SOURCE_EVOLUTION should be true in offset metadata") + } + + test("upgrade from old checkpoint without enforcement config uses default value") { + import org.apache.spark.sql.execution.streaming.checkpointing.{OffsetSeqMetadata, OffsetSeqMetadataV2} + + // Simulate old checkpoint metadata without ENABLE_STREAMING_SOURCE_EVOLUTION + val oldMetadata = OffsetSeqMetadata( + batchWatermarkMs = 0, + batchTimestampMs = 0, + conf = Map( + // Old checkpoint has other configs but not ENABLE_STREAMING_SOURCE_EVOLUTION + SQLConf.STREAMING_MULTIPLE_WATERMARK_POLICY.key -> "max" + ) + ) + + // Verify that reading the config returns the default value (false) + val value = OffsetSeqMetadata.readValueOpt( + oldMetadata, SQLConf.ENABLE_STREAMING_SOURCE_EVOLUTION) + assert(value.contains("false"), + s"Expected default value 'false' for missing config, but got: $value") + + // Also test with V2 metadata + val oldMetadataV2 = OffsetSeqMetadataV2( + batchWatermarkMs = 0, + batchTimestampMs = 0, + conf = Map( + SQLConf.STREAMING_MULTIPLE_WATERMARK_POLICY.key -> "max" + ) + ) + + val valueV2 = OffsetSeqMetadata.readValueOpt( + oldMetadataV2, SQLConf.ENABLE_STREAMING_SOURCE_EVOLUTION) + assert(valueV2.contains("false"), + s"Expected default value 'false' for missing config in V2, but got: $valueV2") + } + + // ============== + // Helper Methods + // ============== + + /** + * Helper method to run tests with source evolution enabled. + * Sets offset log format to V2 (OffsetMap) since named sources require it. + */ + def testWithSourceEvolution(testName: String, testTags: Tag*)(testBody: => Any): Unit = { + test(testName, testTags: _*) { + withSQLConf( + SQLConf.ENABLE_STREAMING_SOURCE_EVOLUTION.key -> "true", + SQLConf.STREAMING_OFFSET_LOG_FORMAT_VERSION.key -> "2") { + testBody + } + } + } +} From 0a7908e95585b1acb154ca7228e6887082fa2a86 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Wed, 25 Feb 2026 10:21:02 -0800 Subject: [PATCH 038/130] [SPARK-55688][BUILD] Upgrade `aircompressor` to 2.0.3 ### What changes were proposed in this pull request? This PR aims to upgrade `aircompressor` to 2.0.3. ### Why are the changes needed? To bring the latest bug fixes. - https://github.com/airlift/aircompressor/releases/tag/2.0.3 ### Does this PR introduce _any_ user-facing change? No behavior change. ### How was this patch tested? Pass the CIs. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54486 from dongjoon-hyun/SPARK-55688. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- dev/deps/spark-deps-hadoop-3-hive-2.3 | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/deps/spark-deps-hadoop-3-hive-2.3 b/dev/deps/spark-deps-hadoop-3-hive-2.3 index 9a0fc1f363f16..16d11f2925236 100644 --- a/dev/deps/spark-deps-hadoop-3-hive-2.3 +++ b/dev/deps/spark-deps-hadoop-3-hive-2.3 @@ -3,7 +3,7 @@ JLargeArrays/1.5//JLargeArrays-1.5.jar JTransforms/3.1//JTransforms-3.1.jar RoaringBitmap/1.6.10//RoaringBitmap-1.6.10.jar ST4/4.0.4//ST4-4.0.4.jar -aircompressor/2.0.2//aircompressor-2.0.2.jar +aircompressor/2.0.3//aircompressor-2.0.3.jar algebra_2.13/2.8.0//algebra_2.13-2.8.0.jar aliyun-java-sdk-core/4.5.10//aliyun-java-sdk-core-4.5.10.jar aliyun-java-sdk-kms/2.11.0//aliyun-java-sdk-kms-2.11.0.jar diff --git a/pom.xml b/pom.xml index 353381376144c..0c46c13871f15 100644 --- a/pom.xml +++ b/pom.xml @@ -2355,7 +2355,7 @@ io.airlift aircompressor - 2.0.2 + 2.0.3 org.apache.orc From d99e5a1449b02bc02754a448e5237ee0359d25e2 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Wed, 25 Feb 2026 11:08:05 -0800 Subject: [PATCH 039/130] Revert "[SPARK-41398][SQL][FOLLOWUP] Update runtime filtering javadocto reflect relaxed partition constraints" ### What changes were proposed in this pull request? This reverts commit 38e51eb5e8d49bed5276a2fc71f1709f643d050f. ### Why are the changes needed? Not only it doesn't make sense to make a follow-up for 3-years old patch, there is a concern about the doc update. We had better get a new JIRA issue for trace-ability. - https://github.com/apache/spark/pull/54330#discussion_r2851832853 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Manual review. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54489 from dongjoon-hyun/SPARK-41398. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- .../spark/sql/connector/read/SupportsRuntimeFiltering.java | 6 ++---- .../sql/connector/read/SupportsRuntimeV2Filtering.java | 7 +++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeFiltering.java b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeFiltering.java index 34bce404f375d..0921a90ac22a7 100644 --- a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeFiltering.java +++ b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeFiltering.java @@ -51,10 +51,8 @@ public interface SupportsRuntimeFiltering extends SupportsRuntimeV2Filtering { * the originally reported partitioning during runtime filtering. While applying runtime filters, * the scan may detect that some {@link InputPartition}s have no matching data. It can omit * such partitions entirely only if it does not report a specific partitioning. Otherwise, - * the scan can either replace the initially planned {@link InputPartition}s that have no - * matching data with empty {@link InputPartition}s, or report only a subset of the original - * partition values (omitting those with no data). The scan must not report new partition values - * that were not present in the original partitioning. + * the scan can replace the initially planned {@link InputPartition}s that have no matching + * data with empty {@link InputPartition}s but must preserve the overall number of partitions. *

* Note that Spark will call {@link Scan#toBatch()} again after filtering the scan at runtime. * diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeV2Filtering.java b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeV2Filtering.java index 1bec81fe8184f..7c238bde969b2 100644 --- a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeV2Filtering.java +++ b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeV2Filtering.java @@ -55,10 +55,9 @@ public interface SupportsRuntimeV2Filtering extends Scan { * the originally reported partitioning during runtime filtering. While applying runtime * predicates, the scan may detect that some {@link InputPartition}s have no matching data. It * can omit such partitions entirely only if it does not report a specific partitioning. - * Otherwise, the scan can either replace the initially planned {@link InputPartition}s that - * have no matching data with empty {@link InputPartition}s, or report only a subset of the - * original partition values (omitting those with no data). The scan must not report new - * partition values that were not present in the original partitioning. + * Otherwise, the scan can replace the initially planned {@link InputPartition}s that have no + * matching data with empty {@link InputPartition}s but must preserve the overall number of + * partitions. *

* Note that Spark will call {@link Scan#toBatch()} again after filtering the scan at runtime. * From 361ee9c465942b10f57ac35f1483e3f516c2c1b7 Mon Sep 17 00:00:00 2001 From: Kent Yao Date: Wed, 25 Feb 2026 11:11:16 -0800 Subject: [PATCH 040/130] [SPARK-54374][SQL][UI][FOLLOWUP] Fix SQL plan visualization display issue caused by initial viewBox MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? This is a follow-up fix for #53864. Replace the initial `viewBox` attribute with `width` and `height` on the SQL plan SVG element. ### Why are the changes needed? Setting `viewBox` before dagre-d3 renders the graph changes the SVG coordinate system, which affects how dagre-d3 positions elements. This causes display issues as reported by pan3793 in https://github.com/apache/spark/pull/53864#issuecomment-3889339344. Using `width` and `height` instead gives a large initial canvas (preventing the tiny default render — the original intent of #53864) without altering the coordinate system that dagre-d3 depends on. The `resizeSvg()` function still correctly sets the final `viewBox`, `width`, and `height` after rendering completes. ### Does this PR introduce _any_ user-facing change? Yes, fixes the SQL plan visualization display regression introduced by #53864. ### How was this patch tested? Tested in Chrome DevTools. ### Was this patch authored or co-authored using generative AI tooling? Yes, GitHub Copilot was used. Closes #54482 from yaooqinn/SPARK-54374. Authored-by: Kent Yao Signed-off-by: Dongjoon Hyun --- .../org/apache/spark/sql/execution/ui/static/spark-sql-viz.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js b/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js index 0065f81a6a363..2b13c93ad4f36 100644 --- a/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js +++ b/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js @@ -29,7 +29,8 @@ function shouldRenderPlanViz() { function renderPlanViz() { var svg = planVizContainer() .append("svg") - .attr("viewBox", `${-PlanVizConstants.svgMarginX} ${-PlanVizConstants.svgMarginY} ${window.innerWidth || 1920} 1000`); + .attr("width", window.innerWidth || 1920) + .attr("height", 1000); var metadata = d3.select("#plan-viz-metadata"); var dot = metadata.select(".dot-file").text().trim(); var graph = svg.append("g"); From 38a75333db72896318177e241b9d0a45d5b99c7b Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Wed, 25 Feb 2026 11:20:49 -0800 Subject: [PATCH 041/130] [SPARK-55694][SQL] Block constraints in CTAS/RTAS at parser level ### What changes were proposed in this pull request? The grammar accepts constraint specifications (PRIMARY KEY, UNIQUE, CHECK, FOREIGN KEY) in CREATE TABLE AS SELECT and REPLACE TABLE AS SELECT, but the execution layer silently drops them. Neither the ANSI SQL standard nor PostgreSQL supports this syntax - the SQL standard makes table element lists and AS subquery clauses mutually exclusive. Block this at the parser level, consistent with existing CTAS/RTAS checks for schema columns and partition column types. ### Why are the changes needed? Explicitly throw exception for an unsupported case for clarity ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? unit test ### Was this patch authored or co-authored using generative AI tooling? Co-Authored-By: Claude Opus 4.6 Closes #54454 from yyanyy/block-ctas-constraints. Authored-by: Yan Yan Signed-off-by: Gengliang Wang --- .../sql/catalyst/parser/AstBuilder.scala | 10 +++++++ .../command/PlanResolutionSuite.scala | 30 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala index 99d76430c3cd9..6fb9cc6799f98 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala @@ -5238,6 +5238,11 @@ class AstBuilder extends DataTypeAstBuilder "Partition column types may not be specified in Create Table As Select (CTAS)", ctx) + case Some(_) if constraints.nonEmpty => + operationNotAllowed( + "Constraints may not be specified in a Create Table As Select (CTAS) statement", + ctx) + case Some(query) => CreateTableAsSelect(identifier, partitioning, query, tableSpec, Map.empty, ifNotExists) @@ -5317,6 +5322,11 @@ class AstBuilder extends DataTypeAstBuilder "Partition column types may not be specified in Replace Table As Select (RTAS)", ctx) + case Some(_) if constraints.nonEmpty => + operationNotAllowed( + "Constraints may not be specified in a Replace Table As Select (RTAS) statement", + ctx) + case Some(query) => ReplaceTableAsSelect(identifier, partitioning, query, tableSpec, writeOptions = Map.empty, orCreate = orCreate) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/PlanResolutionSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/PlanResolutionSuite.scala index 65028eb1777e8..5f5999f67e723 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/PlanResolutionSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/PlanResolutionSuite.scala @@ -3041,6 +3041,36 @@ class PlanResolutionSuite extends SharedSparkSession with AnalysisTest { ExpectedContext(fragment = sql2, start = 0, stop = 61)) } + test("CTAS statement with constraints") { + Seq( + "CONSTRAINT pk PRIMARY KEY (id)", + "CONSTRAINT uk UNIQUE (id)", + "CONSTRAINT ck CHECK (id > 0)" + ).foreach { constraintDef => + val sql = s"CREATE TABLE ctas1 ($constraintDef) AS SELECT 1 AS id" + assertUnsupported( + sql, + Map("message" -> + "Constraints may not be specified in a Create Table As Select (CTAS) statement"), + ExpectedContext(fragment = sql, start = 0, stop = sql.length - 1)) + } + } + + test("RTAS statement with constraints") { + Seq( + "CONSTRAINT pk PRIMARY KEY (id)", + "CONSTRAINT uk UNIQUE (id)", + "CONSTRAINT ck CHECK (id > 0)" + ).foreach { constraintDef => + val sql = s"REPLACE TABLE rtas1 ($constraintDef) AS SELECT 1 AS id" + assertUnsupported( + sql, + Map("message" -> + "Constraints may not be specified in a Replace Table As Select (RTAS) statement"), + ExpectedContext(fragment = sql, start = 0, stop = sql.length - 1)) + } + } + test("create table - basic") { val query = "CREATE TABLE my_table (id int, name string)" val (desc, allowExisting) = extractTableDesc(query) From ebb6817588575d9a4fb6794924c6be0b0af3eb05 Mon Sep 17 00:00:00 2001 From: Takuya Ueshin Date: Wed, 25 Feb 2026 11:50:27 -0800 Subject: [PATCH 042/130] [SPARK-55672][PS][TESTS] Fix error message check due to StringDtype(na_value=nan) ### What changes were proposed in this pull request? Fixes error message check due to `StringDtype(na_value=nan)`. ### Why are the changes needed? The dtype for the default string Series is `StringDtype(na_value=nan)` in pandas 3, which causes to change the error messages. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Updated the related tests. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54465 from ueshin/issues/SPARK-55672/errmsg. Authored-by: Takuya Ueshin Signed-off-by: Takuya Ueshin --- .../pandas/tests/computation/test_compute.py | 8 ++++-- .../pandas/tests/computation/test_stats.py | 12 ++++++--- .../pandas/tests/diff_frames_ops/test_cov.py | 4 +-- .../pandas/tests/series/test_cumulative.py | 8 ++++-- .../pyspark/pandas/tests/series/test_stat.py | 26 ++++++++++++------- 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/python/pyspark/pandas/tests/computation/test_compute.py b/python/pyspark/pandas/tests/computation/test_compute.py index a45132a20a2e4..a8bfa245c1e66 100644 --- a/python/pyspark/pandas/tests/computation/test_compute.py +++ b/python/pyspark/pandas/tests/computation/test_compute.py @@ -384,9 +384,13 @@ def test_quantile(self): pdf.quantile([0.25, 0.5, 0.75], numeric_only=True), ) - with self.assertRaisesRegex(TypeError, "Could not convert object \\(string\\) to numeric"): + with self.assertRaisesRegex( + TypeError, r"Could not convert (object|str) \(string\) to numeric" + ): psdf.quantile(0.5, numeric_only=False) - with self.assertRaisesRegex(TypeError, "Could not convert object \\(string\\) to numeric"): + with self.assertRaisesRegex( + TypeError, r"Could not convert (object|str) \(string\) to numeric" + ): psdf.quantile([0.25, 0.5, 0.75], numeric_only=False) def test_product(self): diff --git a/python/pyspark/pandas/tests/computation/test_stats.py b/python/pyspark/pandas/tests/computation/test_stats.py index 05e9bdd3c6798..6a3ce30060a5f 100644 --- a/python/pyspark/pandas/tests/computation/test_stats.py +++ b/python/pyspark/pandas/tests/computation/test_stats.py @@ -149,11 +149,11 @@ def test_abs(self): self.assert_eq(psdf[["E"]].abs(), pdf[["E"]].abs()) with self.assertRaisesRegex( - TypeError, "bad operand type for abs\\(\\): object \\(string\\)" + TypeError, r"bad operand type for abs\(\): (object|str) \(string\)" ): psdf.abs() with self.assertRaisesRegex( - TypeError, "bad operand type for abs\\(\\): object \\(string\\)" + TypeError, r"bad operand type for abs\(\): (object|str) \(string\)" ): psdf.D.abs() @@ -299,10 +299,14 @@ def test_numeric_only_unsupported(self): psdf[["i", "b"]].sum(numeric_only=False), pdf[["i", "b"]].sum(numeric_only=False) ) - with self.assertRaisesRegex(TypeError, "Could not convert object \\(string\\) to numeric"): + with self.assertRaisesRegex( + TypeError, r"Could not convert (object|str) \(string\) to numeric" + ): psdf.sum(numeric_only=False) - with self.assertRaisesRegex(TypeError, "Could not convert object \\(string\\) to numeric"): + with self.assertRaisesRegex( + TypeError, r"Could not convert (object|str) \(string\) to numeric" + ): psdf.s.sum() diff --git a/python/pyspark/pandas/tests/diff_frames_ops/test_cov.py b/python/pyspark/pandas/tests/diff_frames_ops/test_cov.py index 0240b347081bc..d4b8f6de13501 100644 --- a/python/pyspark/pandas/tests/diff_frames_ops/test_cov.py +++ b/python/pyspark/pandas/tests/diff_frames_ops/test_cov.py @@ -50,9 +50,7 @@ def test_cov(self): psser1 = ps.from_pandas(pser1) with self.assertRaisesRegex(TypeError, "unsupported type: "): psser1.cov([0.12528585, 0.26962463, 0.51111198]) - with self.assertRaisesRegex( - TypeError, "unsupported type: " - ): + with self.assertRaisesRegex(TypeError, f"unsupported type: {pd.Series}"): psser1.cov(pser2) def _test_cov(self, pser1, pser2): diff --git a/python/pyspark/pandas/tests/series/test_cumulative.py b/python/pyspark/pandas/tests/series/test_cumulative.py index a75fe6c0c1320..f24d38a2d8940 100644 --- a/python/pyspark/pandas/tests/series/test_cumulative.py +++ b/python/pyspark/pandas/tests/series/test_cumulative.py @@ -68,7 +68,9 @@ def test_cumsum(self): self.assert_eq(pser.cumsum().astype(int), psser.cumsum()) self.assert_eq(pser.cumsum(skipna=False).astype(int), psser.cumsum(skipna=False)) - with self.assertRaisesRegex(TypeError, r"Could not convert object \(string\) to numeric"): + with self.assertRaisesRegex( + TypeError, r"Could not convert (object|str) \(string\) to numeric" + ): ps.Series(["a", "b", "c", "d"]).cumsum() def test_cumprod(self): @@ -109,7 +111,9 @@ def test_cumprod(self): self.assert_eq(pser.cumprod(), psser.cumprod()) self.assert_eq(pser.cumprod(skipna=False).astype(int), psser.cumprod(skipna=False)) - with self.assertRaisesRegex(TypeError, r"Could not convert object \(string\) to numeric"): + with self.assertRaisesRegex( + TypeError, r"Could not convert (object|str) \(string\) to numeric" + ): ps.Series(["a", "b", "c", "d"]).cumprod() diff --git a/python/pyspark/pandas/tests/series/test_stat.py b/python/pyspark/pandas/tests/series/test_stat.py index 31965e9cdd59d..c94c01583b20f 100644 --- a/python/pyspark/pandas/tests/series/test_stat.py +++ b/python/pyspark/pandas/tests/series/test_stat.py @@ -382,9 +382,13 @@ def test_quantile(self): ): ps.Series([24.0, 21.0, 25.0, 33.0, 26.0]).quantile(q=1.1) - with self.assertRaisesRegex(TypeError, "Could not convert object \\(string\\) to numeric"): + with self.assertRaisesRegex( + TypeError, r"Could not convert (object|str) \(string\) to numeric" + ): ps.Series(["a", "b", "c"]).quantile() - with self.assertRaisesRegex(TypeError, "Could not convert object \\(string\\) to numeric"): + with self.assertRaisesRegex( + TypeError, r"Could not convert (object|str) \(string\) to numeric" + ): ps.Series(["a", "b", "c"]).quantile([0.25, 0.5, 0.75]) def test_pct_change(self): @@ -544,7 +548,9 @@ def test_product(self): ps.Series([]).prod(numeric_only=True) with self.assertRaisesRegex(TypeError, "Could not convert object \\(void\\) to numeric"): ps.Series([]).prod(min_count=1) - with self.assertRaisesRegex(TypeError, "Could not convert object \\(string\\) to numeric"): + with self.assertRaisesRegex( + TypeError, r"Could not convert (object|str) \(string\) to numeric" + ): ps.Series(["a", "b", "c"]).prod() with self.assertRaisesRegex( TypeError, "Could not convert datetime64\\[ns\\] \\(timestamp.*\\) to numeric" @@ -680,19 +686,19 @@ def _test_cov(self, pdf): ) def test_series_stat_fail(self): - with self.assertRaisesRegex(TypeError, "Could not convert object"): + with self.assertRaisesRegex(TypeError, "Could not convert (object|str)"): ps.Series(["a", "b", "c"]).mean() - with self.assertRaisesRegex(TypeError, "Could not convert object"): + with self.assertRaisesRegex(TypeError, "Could not convert (object|str)"): ps.Series(["a", "b", "c"]).skew() - with self.assertRaisesRegex(TypeError, "Could not convert object"): + with self.assertRaisesRegex(TypeError, "Could not convert (object|str)"): ps.Series(["a", "b", "c"]).kurtosis() - with self.assertRaisesRegex(TypeError, "Could not convert object"): + with self.assertRaisesRegex(TypeError, "Could not convert (object|str)"): ps.Series(["a", "b", "c"]).std() - with self.assertRaisesRegex(TypeError, "Could not convert object"): + with self.assertRaisesRegex(TypeError, "Could not convert (object|str)"): ps.Series(["a", "b", "c"]).var() - with self.assertRaisesRegex(TypeError, "Could not convert object"): + with self.assertRaisesRegex(TypeError, "Could not convert (object|str)"): ps.Series(["a", "b", "c"]).median() - with self.assertRaisesRegex(TypeError, "Could not convert object"): + with self.assertRaisesRegex(TypeError, "Could not convert (object|str)"): ps.Series(["a", "b", "c"]).sem() From 6bdae9d0ca7a94f34101a55dc2f7caf0b3f420d7 Mon Sep 17 00:00:00 2001 From: Yicong-Huang <17627829+Yicong-Huang@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:38:03 -0800 Subject: [PATCH 043/130] [SPARK-55666][PYTHON][TEST] Fix flaky connect tests due to non-deterministic row order ### What changes were proposed in this pull request? Use `assertDataFrameEqual` to avoid non-deterministic row order failures. ### Why are the changes needed? Many tests use `assertEqual(cdf.collect(), sdf.collect())` to compare results with bag semantic. Since bags do not guarantee row order, this can fail non-deterministically (flaky test). ### Does this PR introduce any user-facing change? No. ### How was this patch tested? Existing test ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54460 from Yicong-Huang/SPARK-55666/fix/test-join-ambiguous-cols-row-order. Authored-by: Yicong-Huang <17627829+Yicong-Huang@users.noreply.github.com> Signed-off-by: Takuya Ueshin --- .../sql/tests/connect/test_connect_basic.py | 21 +++++++----------- .../tests/connect/test_connect_collection.py | 11 +++++----- .../sql/tests/connect/test_connect_column.py | 4 ++-- .../test_connect_dataframe_property.py | 22 +++++++------------ .../tests/connect/test_connect_function.py | 2 +- 5 files changed, 24 insertions(+), 36 deletions(-) diff --git a/python/pyspark/sql/tests/connect/test_connect_basic.py b/python/pyspark/sql/tests/connect/test_connect_basic.py index 5e2a5bf97796c..6ef0b36c52089 100755 --- a/python/pyspark/sql/tests/connect/test_connect_basic.py +++ b/python/pyspark/sql/tests/connect/test_connect_basic.py @@ -36,6 +36,7 @@ ArrayType, Row, ) +from pyspark.testing import assertDataFrameEqual from pyspark.testing.utils import eventually from pyspark.testing.connectutils import ( should_test_connect, @@ -320,14 +321,12 @@ def test_join_ambiguous_cols(self): cdf3 = cdf1.join(cdf2, cdf1["value"] == cdf2["value"]) sdf3 = sdf1.join(sdf2, sdf1["value"] == sdf2["value"]) - self.assertEqual(cdf3.schema, sdf3.schema) - self.assertEqual(cdf3.collect(), sdf3.collect()) + assertDataFrameEqual(cdf3, sdf3) cdf4 = cdf1.join(cdf2, cdf1["value"].eqNullSafe(cdf2["value"])) sdf4 = sdf1.join(sdf2, sdf1["value"].eqNullSafe(sdf2["value"])) - self.assertEqual(cdf4.schema, sdf4.schema) - self.assertEqual(cdf4.collect(), sdf4.collect()) + assertDataFrameEqual(cdf4, sdf4) cdf5 = cdf1.join( cdf2, (cdf1["value"] == cdf2["value"]) & (cdf1["value"].eqNullSafe(cdf2["value"])) @@ -336,20 +335,17 @@ def test_join_ambiguous_cols(self): sdf2, (sdf1["value"] == sdf2["value"]) & (sdf1["value"].eqNullSafe(sdf2["value"])) ) - self.assertEqual(cdf5.schema, sdf5.schema) - self.assertEqual(cdf5.collect(), sdf5.collect()) + assertDataFrameEqual(cdf5, sdf5) cdf6 = cdf1.join(cdf2, cdf1["value"] == cdf2["value"]).select(cdf1.value) sdf6 = sdf1.join(sdf2, sdf1["value"] == sdf2["value"]).select(sdf1.value) - self.assertEqual(cdf6.schema, sdf6.schema) - self.assertEqual(cdf6.collect(), sdf6.collect()) + assertDataFrameEqual(cdf6, sdf6) cdf7 = cdf1.join(cdf2, cdf1["value"] == cdf2["value"]).select(cdf2.value) sdf7 = sdf1.join(sdf2, sdf1["value"] == sdf2["value"]).select(sdf2.value) - self.assertEqual(cdf7.schema, sdf7.schema) - self.assertEqual(cdf7.collect(), sdf7.collect()) + assertDataFrameEqual(cdf7, sdf7) def test_join_with_cte(self): cte_query = "with dt as (select 1 as ida) select ida as id from dt" @@ -362,8 +358,7 @@ def test_join_with_cte(self): cdf2 = self.connect.sql(cte_query) cdf3 = cdf1.join(cdf2, cdf1.id == cdf2.id) - self.assertEqual(sdf3.schema, cdf3.schema) - self.assertEqual(sdf3.collect(), cdf3.collect()) + assertDataFrameEqual(cdf3, sdf3) def test_with_columns_renamed(self): # SPARK-41312: test DataFrame.withColumnsRenamed() @@ -1621,7 +1616,7 @@ def patched_verify_response_integrity(response): ) # Execute the query, and assert the results are correct. - self.assertEqual(cdf.collect(), sdf.collect()) + assertDataFrameEqual(cdf, sdf) # Verify the metadata of arrow batch chunks. def split_into_batches(chunks): diff --git a/python/pyspark/sql/tests/connect/test_connect_collection.py b/python/pyspark/sql/tests/connect/test_connect_collection.py index ad48c0508d721..0c19d13d4a3fc 100644 --- a/python/pyspark/sql/tests/connect/test_connect_collection.py +++ b/python/pyspark/sql/tests/connect/test_connect_collection.py @@ -15,6 +15,7 @@ # limitations under the License. # +from pyspark.testing import assertDataFrameEqual from pyspark.testing.connectutils import should_test_connect, ReusedMixedTestCase from pyspark.testing.pandasutils import PandasOnSparkTestUtils @@ -62,13 +63,11 @@ def test_collect_timestamp(self): cdf = self.connect.sql(query) sdf = self.spark.sql(query) - self.assertEqual(cdf.schema, sdf.schema) + assertDataFrameEqual(cdf, sdf) - self.assertEqual(cdf.collect(), sdf.collect()) - - self.assertEqual( - cdf.select(CF.date_trunc("year", cdf.date).alias("year")).collect(), - sdf.select(SF.date_trunc("year", sdf.date).alias("year")).collect(), + assertDataFrameEqual( + cdf.select(CF.date_trunc("year", cdf.date).alias("year")), + sdf.select(SF.date_trunc("year", sdf.date).alias("year")), ) def test_head(self): diff --git a/python/pyspark/sql/tests/connect/test_connect_column.py b/python/pyspark/sql/tests/connect/test_connect_column.py index d1d0e9c86e7ff..a048c26a63e54 100644 --- a/python/pyspark/sql/tests/connect/test_connect_column.py +++ b/python/pyspark/sql/tests/connect/test_connect_column.py @@ -41,6 +41,7 @@ BooleanType, ) from pyspark.errors import PySparkTypeError, PySparkValueError +from pyspark.testing import assertDataFrameEqual from pyspark.testing.connectutils import should_test_connect, ReusedMixedTestCase from pyspark.testing.pandasutils import PandasOnSparkTestUtils @@ -996,8 +997,7 @@ def test_with_field_column_name(self): sdf = self.spark.createDataFrame(data) sdf1 = sdf.withColumn("a", sdf["a"].withField("b", SF.lit(3))).select("a.b") - self.assertEqual(cdf1.schema, sdf1.schema) - self.assertEqual(cdf1.collect(), sdf1.collect()) + assertDataFrameEqual(cdf1, sdf1) def test_distributed_sequence_id(self): cdf = self.connect.range(10) diff --git a/python/pyspark/sql/tests/connect/test_connect_dataframe_property.py b/python/pyspark/sql/tests/connect/test_connect_dataframe_property.py index a01293c74b473..318bebf60b0dd 100644 --- a/python/pyspark/sql/tests/connect/test_connect_dataframe_property.py +++ b/python/pyspark/sql/tests/connect/test_connect_dataframe_property.py @@ -28,6 +28,7 @@ ) from pyspark.sql.utils import is_remote from pyspark.sql import functions as SF +from pyspark.testing import assertDataFrameEqual from pyspark.testing.connectutils import should_test_connect, ReusedMixedTestCase from pyspark.testing.pandasutils import PandasOnSparkTestUtils from pyspark.testing.utils import ( @@ -98,8 +99,7 @@ def test_cached_schema_to(self): sdf1 = sdf.to(schema) - self.assertEqual(cdf1.schema, sdf1.schema) - self.assertEqual(cdf1.collect(), sdf1.collect()) + assertDataFrameEqual(cdf1, sdf1) @unittest.skipIf( not have_pandas or not have_pyarrow, @@ -142,8 +142,7 @@ def func(iterator): self.assertFalse(is_remote()) sdf1 = sdf.mapInPandas(func, schema) - self.assertEqual(cdf1.schema, sdf1.schema) - self.assertEqual(cdf1.collect(), sdf1.collect()) + assertDataFrameEqual(cdf1, sdf1) @unittest.skipIf( not have_pandas or not have_pyarrow, @@ -176,8 +175,7 @@ def func(iterator): self.assertFalse(is_remote()) sdf1 = sdf.mapInArrow(func, schema) - self.assertEqual(cdf1.schema, sdf1.schema) - self.assertEqual(cdf1.collect(), sdf1.collect()) + assertDataFrameEqual(cdf1, sdf1) @unittest.skipIf( not have_pandas or not have_pyarrow, @@ -214,8 +212,7 @@ def normalize(pdf): self.assertFalse(is_remote()) sdf1 = sdf.groupby("id").applyInPandas(normalize, schema) - self.assertEqual(cdf1.schema, sdf1.schema) - self.assertEqual(cdf1.collect(), sdf1.collect()) + assertDataFrameEqual(cdf1, sdf1) @unittest.skipIf( not have_pandas or not have_pyarrow, @@ -247,8 +244,7 @@ def normalize(table): self.assertFalse(is_remote()) sdf1 = sdf.groupby("id").applyInArrow(normalize, schema) - self.assertEqual(cdf1.schema, sdf1.schema) - self.assertEqual(cdf1.collect(), sdf1.collect()) + assertDataFrameEqual(cdf1, sdf1) @unittest.skipIf( not have_pandas or not have_pyarrow, @@ -284,8 +280,7 @@ def asof_join(left, right): self.assertFalse(is_remote()) sdf3 = sdf1.groupby("id").cogroup(sdf2.groupby("id")).applyInPandas(asof_join, schema) - self.assertEqual(cdf3.schema, sdf3.schema) - self.assertEqual(cdf3.collect(), sdf3.collect()) + assertDataFrameEqual(cdf3, sdf3) @unittest.skipIf( not have_pandas or not have_pyarrow, @@ -324,8 +319,7 @@ def summarize(left, right): self.assertFalse(is_remote()) sdf3 = sdf1.groupby("id").cogroup(sdf2.groupby("id")).applyInArrow(summarize, schema) - self.assertEqual(cdf3.schema, sdf3.schema) - self.assertEqual(cdf3.collect(), sdf3.collect()) + assertDataFrameEqual(cdf3, sdf3) def test_cached_schema_set_op(self): data1 = [(1, 2, 3)] diff --git a/python/pyspark/sql/tests/connect/test_connect_function.py b/python/pyspark/sql/tests/connect/test_connect_function.py index de1584cb3bc36..e53ed6c70a708 100644 --- a/python/pyspark/sql/tests/connect/test_connect_function.py +++ b/python/pyspark/sql/tests/connect/test_connect_function.py @@ -1672,7 +1672,7 @@ def test_nested_lambda_function(self): # TODO: 'cdf.schema' has an extra metadata '{'__autoGeneratedAlias': 'true'}' self.assertEqual(_drop_metadata(cdf.schema), _drop_metadata(sdf.schema)) - self.assertEqual(cdf.collect(), sdf.collect()) + assertDataFrameEqual(cdf, sdf) def test_csv_functions(self): query = """ From d73c6cba96313acb02797ade72b56ca8efcaa30b Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Thu, 26 Feb 2026 06:57:06 +0900 Subject: [PATCH 044/130] [SPARK-55406][PYTHON][CONNECT][FOLLOW-UP] Add a timeout for release wait ### What changes were proposed in this pull request? Add a timeout when we wait for release to be done ### Why are the changes needed? The underlying gRPC call for release is blocked - so if the server shutdown or in a bad state, it won't be able to tell. We do release in a best-effort way because the server is designed for locating those unused stuff anyway. We had such failures in CI: https://github.com/gaogaotiantian/spark/actions/runs/21923748633/job/63310978801 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? CI ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54279 from gaogaotiantian/add-timeout-for-client-future. Authored-by: Tian Gao Signed-off-by: Hyukjin Kwon --- python/pyspark/sql/connect/client/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pyspark/sql/connect/client/core.py b/python/pyspark/sql/connect/client/core.py index 0a9e8ae3c61c0..f28d97e7472e2 100644 --- a/python/pyspark/sql/connect/client/core.py +++ b/python/pyspark/sql/connect/client/core.py @@ -1271,7 +1271,7 @@ def close(self) -> None: """ Close the channel. """ - concurrent.futures.wait(self._release_futures) + concurrent.futures.wait(self._release_futures, timeout=10) ExecutePlanResponseReattachableIterator.shutdown_threadpool_if_idle() self._channel.close() self._closed = True From b3703755d80585297367d539de9fa8c5783b1c6b Mon Sep 17 00:00:00 2001 From: Anton Okolnychyi Date: Wed, 25 Feb 2026 14:07:14 -0800 Subject: [PATCH 045/130] [SPARK-55631][SQL] ALTER TABLE must invalidate cache for DSv2 tables ### What changes were proposed in this pull request? This PR makes ALTER TABLE command invalidate cache. ### Why are the changes needed? These changes are needed to reflect changes made in the session correctly. ### Does this PR introduce _any_ user-facing change? ALTER TABLE commands will now invalidate cache. ### How was this patch tested? This PR comes with test that would previously fail. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54427 from aokolnychyi/spark-55631. Authored-by: Anton Okolnychyi Signed-off-by: Gengliang Wang --- .../datasources/v2/AlterTableExec.scala | 5 +++-- .../datasources/v2/DataSourceV2Strategy.scala | 6 +++++- .../apache/spark/sql/CachedTableSuite.scala | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/AlterTableExec.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/AlterTableExec.scala index 7b69c5d6f6bd2..fe834f687e493 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/AlterTableExec.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/AlterTableExec.scala @@ -31,7 +31,8 @@ import org.apache.spark.sql.execution.{SparkPlan, UnaryExecNode} case class AlterTableExec( catalog: TableCatalog, ident: Identifier, - changes: Seq[TableChange]) extends LeafV2CommandExec { + changes: Seq[TableChange], + refreshCache: () => Unit) extends LeafV2CommandExec { override def output: Seq[Attribute] = Seq.empty @@ -42,7 +43,7 @@ case class AlterTableExec( case e: IllegalArgumentException if !e.isInstanceOf[SparkThrowable] => throw QueryExecutionErrors.unsupportedTableChangeError(e) } - + refreshCache() Seq.empty } } diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DataSourceV2Strategy.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DataSourceV2Strategy.scala index 81bc1990404a9..014b43c915437 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DataSourceV2Strategy.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DataSourceV2Strategy.scala @@ -579,7 +579,11 @@ class DataSourceV2Strategy(session: SparkSession) extends Strategy with Predicat val table = a.table.asInstanceOf[ResolvedTable] ResolveTableConstraints.validateCatalogForTableChange( a.changes, table.catalog, table.identifier) - AlterTableExec(table.catalog, table.identifier, a.changes) :: Nil + AlterTableExec( + table.catalog, + table.identifier, + a.changes, + recacheTable(table, includeTimeTravel = false)) :: Nil case CreateIndex(ResolvedTable(_, _, table, _), indexName, indexType, ifNotExists, columns, properties) => diff --git a/sql/core/src/test/scala/org/apache/spark/sql/CachedTableSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/CachedTableSuite.scala index 234383239e90f..a928a9131d476 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/CachedTableSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/CachedTableSuite.scala @@ -2663,6 +2663,24 @@ class CachedTableSuite extends QueryTest } } + test("ALTER TABLE invalidates cached table") { + val t = "testcat.tbl" + withTable(t) { + sql(s"CREATE TABLE $t (id int, data string) USING foo") + sql(s"INSERT INTO $t VALUES (1, 'a'), (2, 'b')") + + sql(s"CACHE TABLE $t") + assertCached(sql(s"SELECT * FROM $t")) + checkAnswer(sql(s"SELECT * FROM $t"), Seq(Row(1, "a"), Row(2, "b"))) + + sql(s"ALTER TABLE $t ADD COLUMN new_col int") + + val result = sql(s"SELECT * FROM $t ORDER BY id") + assertCached(result) + checkAnswer(result, Seq(Row(1, "a", null), Row(2, "b", null))) + } + } + private def cacheManager = spark.sharedState.cacheManager private def pinTable( From 53606f21eb1a4dd47be15a2fc353f1dffa23c58d Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Wed, 25 Feb 2026 17:04:24 -0800 Subject: [PATCH 046/130] [SPARK-51695][SQL][DOCS][FOLLOW-UP] Clarify NULL handling semantics in UNIQUE constraint Javadoc ### What changes were proposed in this pull request? Document NULLS DISTINCT behavior: NULL values are treated as distinct from each other, so rows with NULLs in unique columns never conflict. Also note that UNIQUE allows nullable columns (unlike PRIMARY KEY) and that NULLS NOT DISTINCT is not currently supported. ### Why are the changes needed? Better javadoc clarity on UNIQUE constraint expectation. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? N/A ### Was this patch authored or co-authored using generative AI tooling? Co-Authored-By: Claude Opus 4.6 Closes #54357 from yyanyy/unique_definition_clarify. Authored-by: Yan Yan Signed-off-by: Gengliang Wang --- .../spark/sql/connector/catalog/constraints/Unique.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/constraints/Unique.java b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/constraints/Unique.java index d983ef656297e..d4837932863fd 100644 --- a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/constraints/Unique.java +++ b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/constraints/Unique.java @@ -28,6 +28,15 @@ *

* A UNIQUE constraint specifies one or more columns as unique columns. Such constraint is satisfied * if and only if no two rows in a table have the same non-null values in the unique columns. + * Unlike PRIMARY KEY, UNIQUE allows nullable columns. + *

+ * NULL values are treated as distinct from each other (NULLS DISTINCT semantics). Two rows + * are considered duplicates only when every column in the unique key has a non-null value and + * every value matches. If any column in the unique key is NULL, the row is always considered + * unique regardless of other values. In other words, multiple rows with NULL in one or more + * unique columns are allowed and do not violate the constraint definition. + *

+ * The {@code NULLS NOT DISTINCT} modifier is not currently supported. *

* Spark doesn't enforce UNIQUE constraints but leverages them for query optimization. Each * constraint is either valid (the existing data is guaranteed to satisfy the constraint), invalid From 191801b7f34e5c0db2d9a2c62f28117ccb69ac2e Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Thu, 26 Feb 2026 09:52:46 +0800 Subject: [PATCH 047/130] [SPARK-55665][PYTHON] Unify how workers establish connection with the executor ### What changes were proposed in this pull request? Unify all the sock file connections from different worker files together. And guarantee an explicit flush and close for the sock file. ### Why are the changes needed? We now copy/paste this piece of code all over our code base and it introduces a few issues. * Code duplication, obviously. * During the copy/paste, we actually made some mistake. `data_source_pushdown_filters.py` forgets to write pid back but we never test it. * We can't guarantee a flush and close for sock file. Now we rely on gc to do that but that's not reliable. We have issues for simple workers. * In the future, if we want to drop the PID communication (TODO) or for now if we want to do an explicit flush, we need to change all over our code base. It's best to just organize the code at a single place. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Locally `test_python_datasource` passed, the rest is on CI. ### Was this patch authored or co-authored using generative AI tooling? Yes, Cursor(claude-4.6-opus-high). Closes #54458 from gaogaotiantian/sockfile-to-executor. Authored-by: Tian Gao Signed-off-by: Ruifeng Zheng --- .../streaming/worker/foreach_batch_worker.py | 15 +++---------- .../streaming/worker/listener_worker.py | 15 +++---------- .../python_streaming_source_runner.py | 16 ++++---------- .../transform_with_state_driver_worker.py | 14 +++--------- python/pyspark/sql/worker/analyze_udtf.py | 15 +++---------- .../sql/worker/commit_data_source_write.py | 15 +++---------- .../pyspark/sql/worker/create_data_source.py | 14 +++--------- .../worker/data_source_pushdown_filters.py | 12 +++------- .../pyspark/sql/worker/lookup_data_sources.py | 15 +++---------- .../sql/worker/plan_data_source_read.py | 14 +++--------- .../worker/python_streaming_sink_runner.py | 14 +++--------- .../sql/worker/write_into_data_source.py | 17 +++----------- python/pyspark/worker.py | 15 ++++--------- python/pyspark/worker_util.py | 22 ++++++++++++++++++- 14 files changed, 62 insertions(+), 151 deletions(-) diff --git a/python/pyspark/sql/connect/streaming/worker/foreach_batch_worker.py b/python/pyspark/sql/connect/streaming/worker/foreach_batch_worker.py index b819634adb5a6..18bb459a29187 100644 --- a/python/pyspark/sql/connect/streaming/worker/foreach_batch_worker.py +++ b/python/pyspark/sql/connect/streaming/worker/foreach_batch_worker.py @@ -21,7 +21,7 @@ """ import os -from pyspark.util import local_connect_and_auth +from pyspark.worker_util import get_sock_file_to_executor from pyspark.serializers import ( write_int, read_long, @@ -90,14 +90,5 @@ def process(df_id, batch_id): # type: ignore[no-untyped-def] if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, sock) = local_connect_and_auth(conn_info, auth_secret) - # There could be a long time between each micro batch. - sock.settimeout(None) - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor(timeout=None) as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/sql/connect/streaming/worker/listener_worker.py b/python/pyspark/sql/connect/streaming/worker/listener_worker.py index 2c6ce87159948..994339b5d90d6 100644 --- a/python/pyspark/sql/connect/streaming/worker/listener_worker.py +++ b/python/pyspark/sql/connect/streaming/worker/listener_worker.py @@ -22,7 +22,7 @@ import os import json -from pyspark.util import local_connect_and_auth +from pyspark.worker_util import get_sock_file_to_executor from pyspark.serializers import ( read_int, write_int, @@ -104,14 +104,5 @@ def process(listener_event_str, listener_event_type): # type: ignore[no-untyped if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, sock) = local_connect_and_auth(conn_info, auth_secret) - # There could be a long time between each listener event. - sock.settimeout(None) - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor(timeout=None) as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/sql/streaming/python_streaming_source_runner.py b/python/pyspark/sql/streaming/python_streaming_source_runner.py index 31f70a59dbfb1..44811c84548f3 100644 --- a/python/pyspark/sql/streaming/python_streaming_source_runner.py +++ b/python/pyspark/sql/streaming/python_streaming_source_runner.py @@ -48,8 +48,9 @@ StructType, ) from pyspark.sql.worker.plan_data_source_read import records_to_arrow_batches -from pyspark.util import handle_worker_exception, local_connect_and_auth +from pyspark.util import handle_worker_exception from pyspark.worker_util import ( + get_sock_file_to_executor, check_python_version, read_command, pickleSer, @@ -310,14 +311,5 @@ def main(infile: IO, outfile: IO) -> None: if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, sock) = local_connect_and_auth(conn_info, auth_secret) - # Prevent the socket from timeout error when query trigger interval is large. - sock.settimeout(None) - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor(timeout=None) as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/sql/streaming/transform_with_state_driver_worker.py b/python/pyspark/sql/streaming/transform_with_state_driver_worker.py index 3fe7f68a99e56..a05d616eda2cd 100644 --- a/python/pyspark/sql/streaming/transform_with_state_driver_worker.py +++ b/python/pyspark/sql/streaming/transform_with_state_driver_worker.py @@ -15,11 +15,10 @@ # limitations under the License. # -import os import json from typing import Any, Iterator, TYPE_CHECKING -from pyspark.util import local_connect_and_auth +from pyspark.worker_util import get_sock_file_to_executor from pyspark.serializers import ( write_int, read_int, @@ -95,12 +94,5 @@ def process( if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, sock) = local_connect_and_auth(conn_info, auth_secret) - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor() as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/sql/worker/analyze_udtf.py b/python/pyspark/sql/worker/analyze_udtf.py index 7265138202cd9..9328ab2f199b5 100644 --- a/python/pyspark/sql/worker/analyze_udtf.py +++ b/python/pyspark/sql/worker/analyze_udtf.py @@ -16,7 +16,6 @@ # import inspect -import os from textwrap import dedent from typing import Dict, List, IO, Tuple @@ -32,8 +31,8 @@ from pyspark.sql.types import _parse_datatype_json_string, StructType from pyspark.sql.udtf import AnalyzeArgument, AnalyzeResult from pyspark.sql.worker.utils import worker_run -from pyspark.util import local_connect_and_auth from pyspark.worker_util import ( + get_sock_file_to_executor, read_command, pickleSer, utf8_deserializer, @@ -238,13 +237,5 @@ def main(infile: IO, outfile: IO) -> None: if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, _) = local_connect_and_auth(conn_info, auth_secret) - # TODO: Remove the following two lines and use `Process.pid()` when we drop JDK 8. - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor() as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/sql/worker/commit_data_source_write.py b/python/pyspark/sql/worker/commit_data_source_write.py index 6838a32db3983..f16234d29b3d0 100644 --- a/python/pyspark/sql/worker/commit_data_source_write.py +++ b/python/pyspark/sql/worker/commit_data_source_write.py @@ -14,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # -import os from typing import IO from pyspark.errors import PySparkAssertionError @@ -26,8 +25,7 @@ ) from pyspark.sql.datasource import DataSourceWriter, WriterCommitMessage from pyspark.sql.worker.utils import worker_run -from pyspark.util import local_connect_and_auth -from pyspark.worker_util import pickleSer +from pyspark.worker_util import get_sock_file_to_executor, pickleSer def _main(infile: IO, outfile: IO) -> None: @@ -78,12 +76,5 @@ def main(infile: IO, outfile: IO) -> None: if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, _) = local_connect_and_auth(conn_info, auth_secret) - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor() as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/sql/worker/create_data_source.py b/python/pyspark/sql/worker/create_data_source.py index 625b08088e600..41899774a7d3a 100644 --- a/python/pyspark/sql/worker/create_data_source.py +++ b/python/pyspark/sql/worker/create_data_source.py @@ -15,7 +15,6 @@ # limitations under the License. # import inspect -import os from typing import IO from pyspark.errors import PySparkAssertionError, PySparkTypeError @@ -29,8 +28,8 @@ from pyspark.sql.datasource import DataSource, CaseInsensitiveDict from pyspark.sql.types import _parse_datatype_json_string, StructType from pyspark.sql.worker.utils import worker_run -from pyspark.util import local_connect_and_auth from pyspark.worker_util import ( + get_sock_file_to_executor, read_command, pickleSer, utf8_deserializer, @@ -146,12 +145,5 @@ def main(infile: IO, outfile: IO) -> None: if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, _) = local_connect_and_auth(conn_info, auth_secret) - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor() as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/sql/worker/data_source_pushdown_filters.py b/python/pyspark/sql/worker/data_source_pushdown_filters.py index 06b71e1ca8f1a..a649936422996 100644 --- a/python/pyspark/sql/worker/data_source_pushdown_filters.py +++ b/python/pyspark/sql/worker/data_source_pushdown_filters.py @@ -17,7 +17,6 @@ import base64 import json -import os import typing from dataclasses import dataclass, field from typing import IO, Type, Union @@ -47,8 +46,8 @@ from pyspark.sql.types import StructType, VariantVal, _parse_datatype_json_string from pyspark.sql.worker.plan_data_source_read import write_read_func_and_partitions from pyspark.sql.worker.utils import worker_run -from pyspark.util import local_connect_and_auth from pyspark.worker_util import ( + get_sock_file_to_executor, pickleSer, read_command, ) @@ -226,10 +225,5 @@ def main(infile: IO, outfile: IO) -> None: if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, _) = local_connect_and_auth(conn_info, auth_secret) - main(sock_file, sock_file) + with get_sock_file_to_executor() as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/sql/worker/lookup_data_sources.py b/python/pyspark/sql/worker/lookup_data_sources.py index e432f40d6904b..aa5e7c4abb5ae 100644 --- a/python/pyspark/sql/worker/lookup_data_sources.py +++ b/python/pyspark/sql/worker/lookup_data_sources.py @@ -16,7 +16,6 @@ # from importlib import import_module from pkgutil import iter_modules -import os from typing import IO from pyspark.serializers import ( @@ -25,8 +24,7 @@ ) from pyspark.sql.datasource import DataSource from pyspark.sql.worker.utils import worker_run -from pyspark.util import local_connect_and_auth -from pyspark.worker_util import pickleSer +from pyspark.worker_util import get_sock_file_to_executor, pickleSer def _main(infile: IO, outfile: IO) -> None: @@ -60,12 +58,5 @@ def main(infile: IO, outfile: IO) -> None: if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, _) = local_connect_and_auth(conn_info, auth_secret) - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor() as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/sql/worker/plan_data_source_read.py b/python/pyspark/sql/worker/plan_data_source_read.py index ed1c602b0af4b..c858a99462b1c 100644 --- a/python/pyspark/sql/worker/plan_data_source_read.py +++ b/python/pyspark/sql/worker/plan_data_source_read.py @@ -15,7 +15,6 @@ # limitations under the License. # -import os import functools import pyarrow as pa from itertools import islice, chain @@ -44,8 +43,8 @@ StructType, ) from pyspark.sql.worker.utils import worker_run -from pyspark.util import local_connect_and_auth from pyspark.worker_util import ( + get_sock_file_to_executor, read_command, pickleSer, utf8_deserializer, @@ -376,12 +375,5 @@ def main(infile: IO, outfile: IO) -> None: if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, _) = local_connect_and_auth(conn_info, auth_secret) - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor() as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/sql/worker/python_streaming_sink_runner.py b/python/pyspark/sql/worker/python_streaming_sink_runner.py index 952722d0d946c..2a4ea0b95b287 100644 --- a/python/pyspark/sql/worker/python_streaming_sink_runner.py +++ b/python/pyspark/sql/worker/python_streaming_sink_runner.py @@ -15,7 +15,6 @@ # limitations under the License. # -import os from typing import IO from pyspark.errors import PySparkAssertionError @@ -32,8 +31,8 @@ StructType, ) from pyspark.sql.worker.utils import worker_run -from pyspark.util import local_connect_and_auth from pyspark.worker_util import ( + get_sock_file_to_executor, read_command, pickleSer, utf8_deserializer, @@ -113,12 +112,5 @@ def main(infile: IO, outfile: IO) -> None: if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, _) = local_connect_and_auth(conn_info, auth_secret) - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor() as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/sql/worker/write_into_data_source.py b/python/pyspark/sql/worker/write_into_data_source.py index 111829bb7d58f..83bdedb2fdbea 100644 --- a/python/pyspark/sql/worker/write_into_data_source.py +++ b/python/pyspark/sql/worker/write_into_data_source.py @@ -15,7 +15,6 @@ # limitations under the License. # import inspect -import os from typing import IO, Iterable, Iterator from pyspark.sql.conversion import ArrowTableToRowsConversion @@ -24,7 +23,6 @@ from pyspark.serializers import ( read_bool, read_int, - write_int, ) from pyspark.sql import Row from pyspark.sql.datasource import ( @@ -43,10 +41,8 @@ _create_row, ) from pyspark.sql.worker.utils import worker_run -from pyspark.util import ( - local_connect_and_auth, -) from pyspark.worker_util import ( + get_sock_file_to_executor, read_command, pickleSer, utf8_deserializer, @@ -241,12 +237,5 @@ def main(infile: IO, outfile: IO) -> None: if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, _) = local_connect_and_auth(conn_info, auth_secret) - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor() as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/worker.py b/python/pyspark/worker.py index 3717ba6d4d6af..a6ee3f25e4868 100644 --- a/python/pyspark/worker.py +++ b/python/pyspark/worker.py @@ -36,7 +36,7 @@ from pyspark.sql.streaming.stateful_processor_api_client import StatefulProcessorApiClient from pyspark.sql.streaming.stateful_processor_util import TransformWithStateInPandasFuncMode from pyspark.taskcontext import BarrierTaskContext, TaskContext -from pyspark.util import PythonEvalType, local_connect_and_auth +from pyspark.util import PythonEvalType from pyspark.serializers import ( write_int, read_long, @@ -95,6 +95,7 @@ from pyspark.errors import PySparkRuntimeError, PySparkTypeError, PySparkValueError from pyspark.worker_util import ( check_python_version, + get_sock_file_to_executor, read_command, pickleSer, send_accumulator_updates, @@ -3449,13 +3450,5 @@ def process(): if __name__ == "__main__": - # Read information about how to connect back to the JVM from the environment. - conn_info = os.environ.get( - "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) - ) - auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") - (sock_file, _) = local_connect_and_auth(conn_info, auth_secret) - # TODO: Remove the following two lines and use `Process.pid()` when we drop JDK 8. - write_int(os.getpid(), sock_file) - sock_file.flush() - main(sock_file, sock_file) + with get_sock_file_to_executor() as sock_file: + main(sock_file, sock_file) diff --git a/python/pyspark/worker_util.py b/python/pyspark/worker_util.py index ac090bc955bd9..ccf937b5e734a 100644 --- a/python/pyspark/worker_util.py +++ b/python/pyspark/worker_util.py @@ -18,11 +18,12 @@ """ Util functions for workers. """ +from contextlib import contextmanager import importlib from inspect import currentframe, getframeinfo import os import sys -from typing import Any, IO, Optional +from typing import Any, Generator, IO, Optional import warnings if "SPARK_TESTING" in os.environ: @@ -192,6 +193,25 @@ def setup_broadcasts(infile: IO) -> None: broadcast_sock_file.close() +@contextmanager +def get_sock_file_to_executor(timeout: Optional[int] = -1) -> Generator[IO, None, None]: + # Read information about how to connect back to the JVM from the environment. + conn_info = os.environ.get( + "PYTHON_WORKER_FACTORY_SOCK_PATH", int(os.environ.get("PYTHON_WORKER_FACTORY_PORT", -1)) + ) + auth_secret = os.environ.get("PYTHON_WORKER_FACTORY_SECRET") + sock_file, sock = local_connect_and_auth(conn_info, auth_secret) + if timeout is None or timeout > 0: + sock.settimeout(timeout) + # TODO: Remove the following two lines and use `Process.pid()` when we drop JDK 8. + write_int(os.getpid(), sock_file) + sock_file.flush() + try: + yield sock_file + finally: + sock_file.close() + + def send_accumulator_updates(outfile: IO) -> None: """ Send the accumulator updates back to JVM. From 3ca6c0ffb686704091d34f8e0ce8d73171fb3a82 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Wed, 25 Feb 2026 18:17:25 -0800 Subject: [PATCH 048/130] [SPARK-55697][INFRA] Add `create_spark_jira.py` script ### What changes were proposed in this pull request? This PR aims to add `create_spark_jira.py` script in addition to `merge_spark_pr.py`. ### Why are the changes needed? To help the developers via 1. Create ASF JIRA Issue ID. 2. Create a branch with the generated JIRA Issue ID. 3. Help to choose a proper component for the PR (if not given via `-c` CLI argument) 4. Create a commit with the Spark community style commit title at least: `[$JIRA_ID] JIRA_ISSUE_TITLE`. Currently, this script has been used in the `Apache Spark` sub-projects. It's greatly helpful. - https://github.com/apache/spark-kubernetes-operator/blob/main/dev/create_spark_jira.py - https://github.com/apache/spark-connect-swift/blob/main/dev/create_spark_jira.py ### How was this patch tested? Manually. I used this script to prepare this PR. ``` $ dev/create_spark_jira.py -p SPARK-54137 'Add `create_spark_jira.py` script' 1. Block Manager 2. Build 3. Connect 4. Declarative Pipelines 5. Deploy 6. Documentation 7. DStreams 8. Examples 9. Input/Output 10. Java API 11. Kubernetes 12. ML 13. MLlib 14. Optimizer 15. Pandas API on Spark 16. Project Infra 17. Protobuf 18. PySpark 19. Scheduler 20. Security 21. Shuffle 22. Spark Core 23. Spark Docker 24. Spark Shell 25. Spark Submit 26. SQL 27. Structured Streaming 28. Tests 29. Web UI 30. Windows 31. YARN Please choose a component by number: 16 Creating a subtask of SPARK-54137 with title: Add `create_spark_jira.py` script Created JIRA issue: SPARK-55697 git checkout -b SPARK-55697 Switched to a new branch 'SPARK-55697' Created and checked out branch: SPARK-55697 ['git', 'commit', '-a', '-m', '[SPARK-55697] Add `create_spark_jira.py` script'] Created a commit with message: [SPARK-55697] Add `create_spark_jira.py` script ``` ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54495 from dongjoon-hyun/SPARK-55697. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- dev/create_spark_jira.py | 180 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100755 dev/create_spark_jira.py diff --git a/dev/create_spark_jira.py b/dev/create_spark_jira.py new file mode 100755 index 0000000000000..9259bf3adc819 --- /dev/null +++ b/dev/create_spark_jira.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 + +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import argparse +import os +import re +import subprocess +import sys +import traceback + +try: + import jira.client + + JIRA_IMPORTED = True +except ImportError: + JIRA_IMPORTED = False + +# ASF JIRA access token +JIRA_ACCESS_TOKEN = os.environ.get("JIRA_ACCESS_TOKEN") +JIRA_API_BASE = "https://issues.apache.org/jira" + + +def fail(msg): + print(msg) + sys.exit(-1) + + +def run_cmd(cmd): + print(cmd) + if isinstance(cmd, list): + return subprocess.check_output(cmd).decode("utf-8") + else: + return subprocess.check_output(cmd.split(" ")).decode("utf-8") + + +def create_jira_issue(title, parent_jira_id=None, issue_type=None, version=None, component=None): + asf_jira = jira.client.JIRA( + {"server": JIRA_API_BASE}, token_auth=JIRA_ACCESS_TOKEN, timeout=(3.05, 30) + ) + + if version: + affected_version = version + else: + versions = asf_jira.project_versions("SPARK") + # Consider only x.y.z, unreleased, unarchived versions + versions = [ + x + for x in versions + if not x.raw["released"] + and not x.raw["archived"] + and re.match(r"\d+\.\d+\.\d+", x.name) + ] + versions = sorted(versions, key=lambda x: x.name, reverse=True) + affected_version = versions[0].name + + issue_dict = { + "project": {"key": "SPARK"}, + "summary": title, + "description": "", + "versions": [{"name": affected_version}], + } + + if component: + issue_dict["components"] = [{"name": component}] + + if parent_jira_id: + issue_dict["issuetype"] = {"name": "Sub-task"} + issue_dict["parent"] = {"key": parent_jira_id} + else: + issue_dict["issuetype"] = {"name": issue_type if issue_type else "Improvement"} + + try: + new_issue = asf_jira.create_issue(fields=issue_dict) + return new_issue.key + except Exception as e: + fail("Failed to create JIRA issue: %s" % e) + + +def create_and_checkout_branch(jira_id): + try: + run_cmd("git checkout -b %s" % jira_id) + print("Created and checked out branch: %s" % jira_id) + except subprocess.CalledProcessError as e: + fail("Failed to create branch %s: %s" % (jira_id, e)) + + +def create_commit(jira_id, title): + try: + run_cmd(["git", "commit", "-a", "-m", "[%s] %s" % (jira_id, title)]) + print("Created a commit with message: [%s] %s" % (jira_id, title)) + except subprocess.CalledProcessError as e: + fail("Failed to create commit: %s" % e) + + +def choose_components(): + asf_jira = jira.client.JIRA( + {"server": JIRA_API_BASE}, token_auth=JIRA_ACCESS_TOKEN, timeout=(3.05, 30) + ) + components = asf_jira.project_components("SPARK") + components = [c for c in components if not c.raw.get("archived", False)] + for i, c in enumerate(components): + print("%d. %s" % (i + 1, c.name)) + + while True: + try: + choice = input("Please choose a component by number: ") + idx = int(choice) - 1 + if 0 <= idx < len(components): + return components[idx].name + else: + print("Invalid number. Please try again.") + except ValueError: + print("Invalid input. Please enter a number.") + + +def main(): + if not JIRA_IMPORTED: + fail("Could not find jira-python library. Run 'sudo pip3 install jira' to install.") + + if not JIRA_ACCESS_TOKEN: + fail("The env-var JIRA_ACCESS_TOKEN is not set.") + + parser = argparse.ArgumentParser(description="Create a Spark JIRA issue.") + parser.add_argument("title", nargs="?", help="Title of the JIRA issue") + parser.add_argument("-p", "--parent", help="Parent JIRA ID for subtasks") + parser.add_argument( + "-t", + "--type", + help="Issue type to create when no parent is specified (e.g. Bug). Defaults to Improvement.", + ) + parser.add_argument("-v", "--version", help="Version to use for the issue") + parser.add_argument("-c", "--component", help="Component for the issue") + args = parser.parse_args() + + if args.parent: + asf_jira = jira.client.JIRA( + {"server": JIRA_API_BASE}, token_auth=JIRA_ACCESS_TOKEN, timeout=(3.05, 30) + ) + parent_issue = asf_jira.issue(args.parent) + print("Parent issue title: %s" % parent_issue.fields.summary) + print("Creating a subtask of %s with title: %s" % (args.parent, args.title)) + else: + print("Creating JIRA issue with title: %s" % args.title) + + if not args.title: + parser.error("the following arguments are required: title") + + if not args.component: + args.component = choose_components() + + jira_id = create_jira_issue(args.title, args.parent, args.type, args.version, args.component) + print("Created JIRA issue: %s" % jira_id) + + create_and_checkout_branch(jira_id) + + create_commit(jira_id, args.title) + + +if __name__ == "__main__": + try: + main() + except Exception: + traceback.print_exc() + sys.exit(-1) From e3b6b10c70769bafccda58ac8a2b086cc25a6e2d Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Thu, 26 Feb 2026 10:36:35 +0800 Subject: [PATCH 049/130] [SPARK-55671][PYTHON][TESTS] Add zstandard requirement to connect requirement ### What changes were proposed in this pull request? Add `zstandard` check for connect test requirement check. ### Why are the changes needed? `zstandard` is now a requirement for connect so we might as well check it for connect tests. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? CI. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54464 from gaogaotiantian/add-zstandard. Authored-by: Tian Gao Signed-off-by: Ruifeng Zheng --- python/pyspark/testing/utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/pyspark/testing/utils.py b/python/pyspark/testing/utils.py index bc58873e384be..35670d910b54b 100644 --- a/python/pyspark/testing/utils.py +++ b/python/pyspark/testing/utils.py @@ -101,6 +101,9 @@ def have_package(name: str) -> bool: have_grpc_status = have_package("grpc_status") grpc_status_requirement_message = "" if have_grpc_status else "No module named 'grpc_status'" +have_zstandard = have_package("zstandard") +zstandard_requirement_message = "" if have_zstandard else "No module named 'zstandard'" + googleapis_common_protos_requirement_message = "" @@ -140,6 +143,7 @@ def have_package(name: str) -> bool: or grpc_requirement_message or googleapis_common_protos_requirement_message or grpc_status_requirement_message + or zstandard_requirement_message ) should_test_connect = not connect_requirement_message From e92ef557686daf8961a52cfab141b803dde77413 Mon Sep 17 00:00:00 2001 From: Uros Bojanic Date: Thu, 26 Feb 2026 11:32:30 +0800 Subject: [PATCH 050/130] [SPARK-55640][GEO][SQL] Propagate WKB parsing errors for Geometry and Geography ### What changes were proposed in this pull request? WKB reader was implemented for Geometry and Geography, but only using internal exception handling. This PR addresses this by introducing proper user-facing error classes for WKB parsing. ### Why are the changes needed? Propagate the WKB parsing errors properly to the user. ### Does this PR introduce _any_ user-facing change? Yes, users now get proper errors for invalid WKB parsing. ### How was this patch tested? Added new unit tests and end-to-end SQL tests for WKB parsing. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54424 from uros-db/geo-wkb-parse-exceptions. Authored-by: Uros Bojanic Signed-off-by: Wenchen Fan --- .../resources/error/error-conditions.json | 6 ++ python/pyspark/errors/error-conditions.json | 6 ++ python/pyspark/sql/tests/test_functions.py | 26 ++++++ .../spark/sql/catalyst/util/Geography.java | 20 +++-- .../spark/sql/catalyst/util/Geometry.java | 20 +++-- .../catalyst/util/geo/WkbParseException.java | 37 +++------ .../sql/catalyst/util/geo/WkbReader.java | 2 +- .../sql/errors/QueryExecutionErrors.scala | 9 +++ .../util/geo/WkbErrorHandlingTest.java | 58 ++++++-------- .../catalyst/util/geo/WkbGeographyTest.java | 2 +- .../util/geo/WkbReaderWriterAdvancedTest.java | 8 +- .../util/GeographyExecutionSuite.java | 12 +++ .../catalyst/util/GeometryExecutionSuite.java | 12 +++ .../analyzer-results/st-functions.sql.out | 53 ++++++++++++ .../sql-tests/inputs/st-functions.sql | 15 ++++ .../sql-tests/results/st-functions.sql.out | 80 +++++++++++++++++++ .../apache/spark/sql/STExpressionsSuite.scala | 35 ++++++++ .../apache/spark/sql/STFunctionsSuite.scala | 39 +++++++++ 18 files changed, 359 insertions(+), 81 deletions(-) diff --git a/common/utils/src/main/resources/error/error-conditions.json b/common/utils/src/main/resources/error/error-conditions.json index dc6200095444c..94111b8e9ee0f 100644 --- a/common/utils/src/main/resources/error/error-conditions.json +++ b/common/utils/src/main/resources/error/error-conditions.json @@ -7754,6 +7754,12 @@ ], "sqlState" : "42601" }, + "WKB_PARSE_ERROR" : { + "message" : [ + "Error parsing WKB: at position " + ], + "sqlState" : "22023" + }, "WRITE_STREAM_NOT_ALLOWED" : { "message" : [ "`writeStream` can be called only on streaming Dataset/DataFrame." diff --git a/python/pyspark/errors/error-conditions.json b/python/pyspark/errors/error-conditions.json index 94ede56da5e1f..b0cf4c084e201 100644 --- a/python/pyspark/errors/error-conditions.json +++ b/python/pyspark/errors/error-conditions.json @@ -1488,6 +1488,12 @@ "Value for `` must be between and (inclusive), got " ] }, + "WKB_PARSE_ERROR" : { + "message" : [ + "Error parsing WKB: at position " + ], + "sqlState" : "22023" + }, "WRONG_NUM_ARGS_FOR_HIGHER_ORDER_FUNCTION": { "message": [ "Function `` should take between 1 and 3 arguments, but the provided function takes ." diff --git a/python/pyspark/sql/tests/test_functions.py b/python/pyspark/sql/tests/test_functions.py index 9313cd34dc06e..cdfd8cc24cd04 100644 --- a/python/pyspark/sql/tests/test_functions.py +++ b/python/pyspark/sql/tests/test_functions.py @@ -26,6 +26,7 @@ import unittest from pyspark.errors import PySparkTypeError, PySparkValueError, SparkRuntimeException +from pyspark.errors.exceptions.base import IllegalArgumentException from pyspark.sql import Row, Window, functions as F, types from pyspark.sql.avro.functions import from_avro, to_avro from pyspark.sql.column import Column @@ -3798,6 +3799,25 @@ def test_st_asbinary(self): ) self.assertEqual(results, [expected]) + def test_st_geogfromwkb(self): + df = self.spark.createDataFrame( + [(bytes.fromhex("0101000000000000000000F03F0000000000000040"),)], + ["wkb"], + ) + results = df.select( + F.hex(F.st_asbinary(F.st_geogfromwkb("wkb"))), + ).collect() + expected = Row( + "0101000000000000000000F03F0000000000000040", + ) + self.assertEqual(results, [expected]) + # ST_GeogFromWKB with invalid WKB. + df = self.spark.createDataFrame([(bytearray(b"\x6f"),)], ["wkb"]) + with self.assertRaises(IllegalArgumentException) as error_context: + df.select(F.st_geogfromwkb("wkb")).collect() + self.assertIn("[WKB_PARSE_ERROR]", str(error_context.exception)) + self.assertIn("Unexpected end of WKB buffer", str(error_context.exception)) + def test_st_geomfromwkb(self): df = self.spark.createDataFrame( [(bytes.fromhex("0101000000000000000000F03F0000000000000040"), 4326)], @@ -3814,6 +3834,12 @@ def test_st_geomfromwkb(self): "0101000000000000000000F03F0000000000000040", ) self.assertEqual(results, [expected]) + # ST_GeomFromWKB with invalid WKB. + df = self.spark.createDataFrame([(bytearray(b"\x6f"),)], ["wkb"]) + with self.assertRaises(IllegalArgumentException) as error_context: + df.select(F.st_geomfromwkb("wkb")).collect() + self.assertIn("[WKB_PARSE_ERROR]", str(error_context.exception)) + self.assertIn("Unexpected end of WKB buffer", str(error_context.exception)) def test_st_setsrid(self): df = self.spark.createDataFrame( diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geography.java b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geography.java index 445e30af15b86..f446d71d5a5b8 100644 --- a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geography.java +++ b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geography.java @@ -17,8 +17,10 @@ package org.apache.spark.sql.catalyst.util; import org.apache.spark.sql.catalyst.util.geo.GeometryModel; +import org.apache.spark.sql.catalyst.util.geo.WkbParseException; import org.apache.spark.sql.catalyst.util.geo.WkbReader; import org.apache.spark.sql.catalyst.util.geo.WkbWriter; +import org.apache.spark.sql.errors.QueryExecutionErrors; import org.apache.spark.unsafe.types.GeographyVal; import java.nio.ByteBuffer; @@ -81,13 +83,17 @@ public Geography copy() { // Returns a Geography object with the specified SRID value by parsing the input WKB. public static Geography fromWkb(byte[] wkb, int srid) { - WkbReader reader = new WkbReader(true); - reader.read(wkb); // Validate WKB with geography coordinate bounds. - - byte[] bytes = new byte[HEADER_SIZE + wkb.length]; - ByteBuffer.wrap(bytes).order(DEFAULT_ENDIANNESS).putInt(srid); - System.arraycopy(wkb, 0, bytes, WKB_OFFSET, wkb.length); - return fromBytes(bytes); + try { + WkbReader reader = new WkbReader(true); + reader.read(wkb); // Validate WKB with geography coordinate bounds. + + byte[] bytes = new byte[HEADER_SIZE + wkb.length]; + ByteBuffer.wrap(bytes).order(DEFAULT_ENDIANNESS).putInt(srid); + System.arraycopy(wkb, 0, bytes, WKB_OFFSET, wkb.length); + return fromBytes(bytes); + } catch (WkbParseException e) { + throw QueryExecutionErrors.wkbParseError(e.getParseError(), e.getPosition()); + } } // Overload for the WKB reader where we use the default SRID for Geography. diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geometry.java b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geometry.java index 757c63f421e71..58be589b86ff7 100644 --- a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geometry.java +++ b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/Geometry.java @@ -17,8 +17,10 @@ package org.apache.spark.sql.catalyst.util; import org.apache.spark.sql.catalyst.util.geo.GeometryModel; +import org.apache.spark.sql.catalyst.util.geo.WkbParseException; import org.apache.spark.sql.catalyst.util.geo.WkbReader; import org.apache.spark.sql.catalyst.util.geo.WkbWriter; +import org.apache.spark.sql.errors.QueryExecutionErrors; import org.apache.spark.unsafe.types.GeometryVal; import java.nio.ByteBuffer; @@ -81,13 +83,17 @@ public Geometry copy() { // Returns a Geometry object with the specified SRID value by parsing the input WKB. public static Geometry fromWkb(byte[] wkb, int srid) { - WkbReader reader = new WkbReader(); - reader.read(wkb); // Validate WKB - - byte[] bytes = new byte[HEADER_SIZE + wkb.length]; - ByteBuffer.wrap(bytes).order(DEFAULT_ENDIANNESS).putInt(srid); - System.arraycopy(wkb, 0, bytes, WKB_OFFSET, wkb.length); - return fromBytes(bytes); + try { + WkbReader reader = new WkbReader(); + reader.read(wkb); // Validate WKB + + byte[] bytes = new byte[HEADER_SIZE + wkb.length]; + ByteBuffer.wrap(bytes).order(DEFAULT_ENDIANNESS).putInt(srid); + System.arraycopy(wkb, 0, bytes, WKB_OFFSET, wkb.length); + return fromBytes(bytes); + } catch (WkbParseException e) { + throw QueryExecutionErrors.wkbParseError(e.getParseError(), e.getPosition()); + } } // Overload for the WKB reader where we use the default SRID for Geometry. diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/WkbParseException.java b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/WkbParseException.java index 3ea8e95e7cc43..b1d1b4dfba1a8 100644 --- a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/WkbParseException.java +++ b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/WkbParseException.java @@ -19,40 +19,27 @@ /** * Exception thrown when parsing WKB data fails. */ -class WkbParseException extends RuntimeException { +public class WkbParseException extends RuntimeException { + private final String parseError; private final long position; - private final String wkbString; + private final byte[] wkb; - WkbParseException(String message, long position, byte[] wkb) { - super(formatMessage(message, position, wkb)); + WkbParseException(String parseError, long position, byte[] wkb) { + super(); + this.parseError = parseError; this.position = position; - this.wkbString = wkb != null ? bytesToHex(wkb) : ""; + this.wkb = wkb; } - private static String formatMessage(String message, long position, byte[] wkb) { - String baseMessage = message + " at position " + position; - if (wkb != null && wkb.length > 0) { - baseMessage += " in WKB: " + bytesToHex(wkb); - } - return baseMessage; + public String getParseError() { + return parseError; } - private static String bytesToHex(byte[] bytes) { - if (bytes == null || bytes.length == 0) { - return ""; - } - StringBuilder sb = new StringBuilder(bytes.length * 2); - for (byte b : bytes) { - sb.append(String.format("%02X", b)); - } - return sb.toString(); - } - - long getPosition() { + public long getPosition() { return position; } - String getWkbString() { - return wkbString; + public byte[] getWkb() { + return wkb; } } diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/WkbReader.java b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/WkbReader.java index e0b8b543300b4..9546ec7cf1842 100644 --- a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/WkbReader.java +++ b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/geo/WkbReader.java @@ -222,7 +222,7 @@ private GeometryModel readGeometry(int defaultSrid) { // Check that we have enough bytes for header (endianness byte + 4-byte type) if (currentWkb.length < WkbUtil.BYTE_SIZE + WkbUtil.TYPE_SIZE) { - throw new WkbParseException("WKB data too short", 0, currentWkb); + throw new WkbParseException("Unexpected end of WKB buffer", 0, currentWkb); } // Create buffer wrapping the entire byte array diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala index 4e7cfa6533890..8985bdb519d19 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala @@ -676,6 +676,15 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE stInvalidSridValueError(srid.toString) } + def wkbParseError(msg: String, pos: String): SparkIllegalArgumentException = { + new SparkIllegalArgumentException(errorClass = "WKB_PARSE_ERROR", + messageParameters = Map("parseError" -> msg, "pos" -> pos)) + } + + def wkbParseError(msg: String, pos: Long): SparkIllegalArgumentException = { + wkbParseError(msg, pos.toString) + } + def withSuggestionIntervalArithmeticOverflowError( suggestedFunc: String, context: QueryContext): ArithmeticException = { diff --git a/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbErrorHandlingTest.java b/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbErrorHandlingTest.java index 660775a1adc8e..f66bc50daf98b 100644 --- a/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbErrorHandlingTest.java +++ b/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbErrorHandlingTest.java @@ -46,13 +46,12 @@ private void assertParseError(String hex, String expectedMessagePart, int valida WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> reader.read(wkb), "Should throw WkbParseException for WKB: " + hex); - Assertions.assertTrue(ex.getMessage().toUpperCase().contains(hex.toUpperCase()), - "Exception message should contain the WKB hex: " + hex + ", actual: " + ex.getMessage()); + Assertions.assertSame(wkb, ex.getWkb()); if (expectedMessagePart != null && !expectedMessagePart.isEmpty()) { Assertions.assertTrue( - ex.getMessage().toLowerCase().contains(expectedMessagePart.toLowerCase()), + ex.getParseError().toLowerCase().contains(expectedMessagePart.toLowerCase()), "Exception message should contain '" + expectedMessagePart + "', actual: " + - ex.getMessage()); + ex.getParseError()); } } @@ -63,69 +62,60 @@ public void testEmptyWkb() { WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> reader.read(emptyWkb)); // Empty WKB produces empty hex string, so just verify exception was thrown - Assertions.assertNotNull(ex.getMessage()); + Assertions.assertNotNull(ex.getParseError()); } @Test public void testTooShortWkb() { // Only endianness byte - String hex = "01"; - byte[] tooShort = hexToBytes(hex); + byte[] tooShort = hexToBytes("01"); WkbReader reader = new WkbReader(); WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> reader.read(tooShort)); - Assertions.assertTrue(ex.getMessage().toUpperCase().contains(hex.toUpperCase()), - "Exception message should contain the WKB hex: " + hex); + Assertions.assertSame(tooShort, ex.getWkb()); } @Test public void testInvalidGeometryTypeZero() { // Type = 0 (invalid, should be 1-7) - String hex = "0100000000000000000000F03F0000000000000040"; - byte[] invalidType = hexToBytes(hex); + byte[] invalidType = hexToBytes("0100000000000000000000F03F0000000000000040"); WkbReader reader = new WkbReader(); WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> reader.read(invalidType)); - Assertions.assertTrue(ex.getMessage().toUpperCase().contains(hex.toUpperCase()), - "Exception message should contain the WKB hex: " + hex); + Assertions.assertSame(invalidType, ex.getWkb()); } @Test public void testTruncatedPointCoordinates() { // Point WKB with truncated coordinates (missing Y coordinate) - String hex = "0101000000000000000000F03F"; - byte[] truncated = hexToBytes(hex); + byte[] truncated = hexToBytes("0101000000000000000000F03F"); WkbReader reader = new WkbReader(); WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> reader.read(truncated)); - Assertions.assertTrue(ex.getMessage().toUpperCase().contains(hex.toUpperCase()), - "Exception message should contain the WKB hex: " + hex); + Assertions.assertSame(truncated, ex.getWkb()); } @Test public void testTruncatedByte() { // Only one byte (FF) of the 4-byte INT field. - String hex = "0102000000ff"; - byte[] truncated = hexToBytes(hex); + byte[] truncated = hexToBytes("0102000000ff"); WkbReader reader = new WkbReader(); WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> reader.read(truncated)); - Assertions.assertTrue(ex.getMessage().toUpperCase().contains(hex.toUpperCase()), - "Exception message should contain the WKB hex: " + hex); + Assertions.assertSame(truncated, ex.getWkb()); } @Test public void testTruncatedLineString() { // LineString with declared 2 points but only 1 provided - String hex = "010200000002000000" + // LineString with 2 points - "0000000000000000" + // X of first point - "0000000000000000"; // Y of first point (missing second point) - byte[] truncated = hexToBytes(hex); + byte[] truncated = hexToBytes( + "010200000002000000" + // LineString with 2 points + "0000000000000000" + // X of first point + "0000000000000000"); // Y of first point (missing second point) WkbReader reader = new WkbReader(); WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> reader.read(truncated)); - Assertions.assertTrue(ex.getMessage().toUpperCase().contains(hex.toUpperCase()), - "Exception message should contain the WKB hex: " + hex); + Assertions.assertSame(truncated, ex.getWkb()); } @Test @@ -164,8 +154,7 @@ public void testRingWithTooFewPoints() { WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> reader.read(invalidPolygon)); - Assertions.assertTrue(ex.getMessage().toUpperCase().contains(hex.toUpperCase()), - "Exception message should contain the WKB hex: " + hex); + Assertions.assertSame(invalidPolygon, ex.getWkb()); } @Test @@ -174,20 +163,19 @@ public void testNonClosedRing() { WkbReader reader = new WkbReader(1); // Polygon with ring where first and last points don't match - String hex = "01" + // Little endian + byte[] nonClosedRing = hexToBytes( + "01" + // Little endian "03000000" + // Polygon type "01000000" + // 1 ring "04000000" + // 4 points "0000000000000000" + "0000000000000000" + // (0, 0) "000000000000F03F" + "0000000000000000" + // (1, 0) "000000000000F03F" + "000000000000F03F" + // (1, 1) - "0000000000000040" + "0000000000000040"; // (2, 2) - doesn't match first point! - byte[] nonClosedRing = hexToBytes(hex); + "0000000000000040" + "0000000000000040"); // (2, 2) - doesn't match first point! WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> reader.read(nonClosedRing)); - Assertions.assertTrue(ex.getMessage().toUpperCase().contains(hex.toUpperCase()), - "Exception message should contain the WKB hex: " + hex); + Assertions.assertSame(nonClosedRing, ex.getWkb()); } @Test @@ -197,7 +185,7 @@ public void testNullByteArray() { WkbParseException.class, () -> reader.read(null), "Should throw WKBParseException for null byte array"); // Null WKB cannot produce hex string, just verify exception was thrown - Assertions.assertNotNull(ex.getMessage()); + Assertions.assertNotNull(ex.getParseError()); } // ========== Invalid Byte Order Tests ========== diff --git a/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbGeographyTest.java b/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbGeographyTest.java index 5c9412519216d..04e98ac8da9c6 100644 --- a/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbGeographyTest.java +++ b/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbGeographyTest.java @@ -629,7 +629,7 @@ public void testGeographyErrorMessageContainsBoundsInfo() { byte[] wkb = makePointWkb2D(200.0, 0.0); WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> geographyReader1().read(wkb)); - String msg = ex.getMessage(); + String msg = ex.getParseError(); Assertions.assertTrue(msg.contains("Invalid coordinate value")); } } diff --git a/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbReaderWriterAdvancedTest.java b/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbReaderWriterAdvancedTest.java index 98bec81ca0114..c02f1f196e385 100644 --- a/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbReaderWriterAdvancedTest.java +++ b/sql/catalyst/src/test/java/org/apache/spark/sql/catalyst/util/geo/WkbReaderWriterAdvancedTest.java @@ -55,8 +55,7 @@ private void checkWkbParsing(String wkbHexLittle, String wkbHexBig, GeoTypeId ex if (expectedValidateError) { WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> validateReader.read(wkbLittle, 0)); - Assertions.assertTrue(ex.getMessage().toUpperCase().contains(wkbHexLittle.toUpperCase()), - "Exception message should contain the WKB hex: " + wkbHexLittle); + Assertions.assertSame(wkbLittle, ex.getWkb()); geomLittle = noValidateReader.read(wkbLittle, 0); } else { geomLittle = validateReader.read(wkbLittle, 0); @@ -73,8 +72,7 @@ private void checkWkbParsing(String wkbHexLittle, String wkbHexBig, GeoTypeId ex if (expectedValidateError) { WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> validateReader.read(wkbBig, 0)); - Assertions.assertTrue(ex.getMessage().toUpperCase().contains(wkbHexBig.toUpperCase()), - "Exception message should contain the WKB hex: " + wkbHexBig); + Assertions.assertSame(wkbBig, ex.getWkb()); geomBig = noValidateReader.read(wkbBig, 0); } else { geomBig = validateReader.read(wkbBig, 0); @@ -1198,7 +1196,7 @@ private void checkGeographyBoundsError(String wkbHexLe, String wkbHexBe) { WkbReader geographyReader = new WkbReader(true); WkbParseException ex = Assertions.assertThrows( WkbParseException.class, () -> geographyReader.read(wkb, 0)); - Assertions.assertTrue(ex.getMessage().contains("Invalid coordinate value")); + Assertions.assertTrue(ex.getParseError().contains("Invalid coordinate value")); // Geography mode without validation should accept non-geographic coordinate values. WkbReader noValidateGeographyReader = new WkbReader(0, true); Assertions.assertDoesNotThrow(() -> noValidateGeographyReader.read(wkb, 0)); diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeographyExecutionSuite.java b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeographyExecutionSuite.java index d7c40047977a4..fece3e36bc593 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeographyExecutionSuite.java +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeographyExecutionSuite.java @@ -17,6 +17,7 @@ package org.apache.spark.sql.catalyst.util; +import org.apache.spark.SparkIllegalArgumentException; import org.apache.spark.unsafe.types.GeographyVal; import org.junit.jupiter.api.Test; @@ -113,6 +114,17 @@ void testFromWkbNoSridRudimentary() { assertEquals(4326, geography.srid()); } + @Test + void testFromWkbInvalidWkb() { + byte[] invalidWkb = new byte[]{111}; + SparkIllegalArgumentException exception = assertThrows( + SparkIllegalArgumentException.class, + () -> Geometry.fromWkb(invalidWkb) + ); + assertEquals("WKB_PARSE_ERROR", exception.getCondition()); + assertTrue(exception.getMessage().contains("Unexpected end of WKB buffer")); + } + /** Tests for Geography EWKB parsing. */ @Test diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeometryExecutionSuite.java b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeometryExecutionSuite.java index 617ef7752a05c..5d0b11e969ad3 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeometryExecutionSuite.java +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/GeometryExecutionSuite.java @@ -17,6 +17,7 @@ package org.apache.spark.sql.catalyst.util; +import org.apache.spark.SparkIllegalArgumentException; import org.apache.spark.unsafe.types.GeometryVal; import org.junit.jupiter.api.Test; @@ -127,6 +128,17 @@ void testFromWkbNoSridRudimentary() { assertEquals(0, geometry.srid()); } + @Test + void testFromWkbInvalidWkb() { + byte[] invalidWkb = new byte[]{111}; + SparkIllegalArgumentException exception = assertThrows( + SparkIllegalArgumentException.class, + () -> Geometry.fromWkb(invalidWkb) + ); + assertEquals("WKB_PARSE_ERROR", exception.getCondition()); + assertTrue(exception.getMessage().contains("Unexpected end of WKB buffer")); + } + /** Tests for Geometry EWKB parsing. */ @Test diff --git a/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out b/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out index 8391c4800d8b9..7566e69392fdc 100644 --- a/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out +++ b/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out @@ -466,6 +466,45 @@ Project [hex(st_asbinary(st_geomfromwkb(0x0101000000000000000000F03F000000000000 +- OneRowRelation +-- !query +SELECT ST_AsBinary(ST_GeogFromWKB(NULL)) +-- !query analysis +Project [st_asbinary(st_geogfromwkb(cast(null as binary))) AS st_asbinary(st_geogfromwkb(NULL))#x] ++- OneRowRelation + + +-- !query +SELECT hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'))) +-- !query analysis +Project [hex(st_asbinary(st_geogfromwkb(0x0101000000000000000000F03F0000000000000040))) AS hex(st_asbinary(st_geogfromwkb(X'0101000000000000000000F03F0000000000000040')))#x] ++- OneRowRelation + + +-- !query +SELECT ST_GeogFromWKB(X'6F') +-- !query analysis +Project [st_geogfromwkb(0x6F) AS st_geogfromwkb(X'6F')#x] ++- OneRowRelation + + +-- !query +SELECT COUNT(*) FROM geodata WHERE ST_GeogFromWKB(wkb) IS NULL AND wkb IS NOT NULL +-- !query analysis +Aggregate [count(1) AS count(1)#xL] ++- Filter (isnull(st_geogfromwkb(wkb#x)) AND isnotnull(wkb#x)) + +- SubqueryAlias spark_catalog.default.geodata + +- Relation spark_catalog.default.geodata[wkb#x] parquet + + +-- !query +SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb)) <> wkb +-- !query analysis +Aggregate [count(1) AS count(1)#xL] ++- Filter NOT (st_asbinary(st_geogfromwkb(wkb#x)) = wkb#x) + +- SubqueryAlias spark_catalog.default.geodata + +- Relation spark_catalog.default.geodata[wkb#x] parquet + + -- !query SELECT ST_AsBinary(ST_GeomFromWKB(NULL)) -- !query analysis @@ -527,6 +566,20 @@ org.apache.spark.SparkIllegalArgumentException } +-- !query +SELECT ST_GeomFromWKB(X'6F') +-- !query analysis +Project [st_geomfromwkb(0x6F, 0) AS st_geomfromwkb(X'6F', 0)#x] ++- OneRowRelation + + +-- !query +SELECT ST_GeomFromWKB(X'6F', 4326) +-- !query analysis +Project [st_geomfromwkb(0x6F, 4326) AS st_geomfromwkb(X'6F', 4326)#x] ++- OneRowRelation + + -- !query SELECT COUNT(*) FROM geodata WHERE ST_GeomFromWKB(wkb) IS NULL AND wkb IS NOT NULL -- !query analysis diff --git a/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql b/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql index c12b79fb28693..f3543837ddfc3 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql @@ -95,6 +95,18 @@ SELECT typeof(IF(wkb IS NOT NULL, ST_GeomFromWKB(wkb)::GEOMETRY(ANY), ST_GeomFro SELECT hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000f03f0000000000000040'))) AS result; SELECT hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040'))) AS result; +---- ST_GeogFromWKB + +-- 1. Driver-level queries. +SELECT ST_AsBinary(ST_GeogFromWKB(NULL)); +SELECT hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'))); +-- Error handling: invalid WKB. +SELECT ST_GeogFromWKB(X'6F'); + +-- 2. Table-level queries. +SELECT COUNT(*) FROM geodata WHERE ST_GeogFromWKB(wkb) IS NULL AND wkb IS NOT NULL; +SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb)) <> wkb; + ---- ST_GeomFromWKB -- 1. Driver-level queries. @@ -106,6 +118,9 @@ SELECT hex(ST_AsBinary(ST_GeomFromWKB(X'0101000000000000000000F03F00000000000000 -- Error handling: invalid SRID. SELECT ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040', -1); SELECT ST_GeomFromWKB(X'0101000000000000000000F03F0000000000000040', 9999); +-- Error handling: invalid WKB. +SELECT ST_GeomFromWKB(X'6F'); +SELECT ST_GeomFromWKB(X'6F', 4326); -- 2. Table-level queries. SELECT COUNT(*) FROM geodata WHERE ST_GeomFromWKB(wkb) IS NULL AND wkb IS NOT NULL; diff --git a/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out b/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out index c4b0fbeec5be2..03f5728d7d3a6 100644 --- a/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out @@ -523,6 +523,54 @@ struct 0101000000000000000000F03F0000000000000040 +-- !query +SELECT ST_AsBinary(ST_GeogFromWKB(NULL)) +-- !query schema +struct +-- !query output +NULL + + +-- !query +SELECT hex(ST_AsBinary(ST_GeogFromWKB(X'0101000000000000000000F03F0000000000000040'))) +-- !query schema +struct +-- !query output +0101000000000000000000F03F0000000000000040 + + +-- !query +SELECT ST_GeogFromWKB(X'6F') +-- !query schema +struct<> +-- !query output +org.apache.spark.SparkIllegalArgumentException +{ + "errorClass" : "WKB_PARSE_ERROR", + "sqlState" : "22023", + "messageParameters" : { + "parseError" : "Unexpected end of WKB buffer", + "pos" : "0" + } +} + + +-- !query +SELECT COUNT(*) FROM geodata WHERE ST_GeogFromWKB(wkb) IS NULL AND wkb IS NOT NULL +-- !query schema +struct +-- !query output +0 + + +-- !query +SELECT COUNT(*) FROM geodata WHERE ST_AsBinary(ST_GeogFromWKB(wkb)) <> wkb +-- !query schema +struct +-- !query output +0 + + -- !query SELECT ST_AsBinary(ST_GeomFromWKB(NULL)) -- !query schema @@ -593,6 +641,38 @@ org.apache.spark.SparkIllegalArgumentException } +-- !query +SELECT ST_GeomFromWKB(X'6F') +-- !query schema +struct<> +-- !query output +org.apache.spark.SparkIllegalArgumentException +{ + "errorClass" : "WKB_PARSE_ERROR", + "sqlState" : "22023", + "messageParameters" : { + "parseError" : "Unexpected end of WKB buffer", + "pos" : "0" + } +} + + +-- !query +SELECT ST_GeomFromWKB(X'6F', 4326) +-- !query schema +struct<> +-- !query output +org.apache.spark.SparkIllegalArgumentException +{ + "errorClass" : "WKB_PARSE_ERROR", + "sqlState" : "22023", + "messageParameters" : { + "parseError" : "Unexpected end of WKB buffer", + "pos" : "0" + } +} + + -- !query SELECT COUNT(*) FROM geodata WHERE ST_GeomFromWKB(wkb) IS NULL AND wkb IS NOT NULL -- !query schema diff --git a/sql/core/src/test/scala/org/apache/spark/sql/STExpressionsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/STExpressionsSuite.scala index 33274c05b899d..4716818e5e36f 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/STExpressionsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/STExpressionsSuite.scala @@ -488,6 +488,31 @@ class STExpressionsSuite checkEvaluation(ST_AsBinary(geometryExpression), wkb) } + test("ST_GeogFromWKB - expressions") { + // Test data: WKB representation of POINT(1 2). + val wkb = Hex.unhex("0101000000000000000000F03F0000000000000040".getBytes()) + val wkbLiteral = Literal.create(wkb, BinaryType) + // ST_GeogFromWKB with default SRID. + val geographyExpression = ST_GeogFromWKB(wkbLiteral) + assert(geographyExpression.dataType.sameType(defaultGeographyType)) + checkEvaluation(ST_AsBinary(geographyExpression), wkb) + checkEvaluation(ST_Srid(geographyExpression), defaultGeographySrid) + // ST_GeogFromWKB with NULL input. + val nullLiteral = Literal.create(null, BinaryType) + val geographyExpressionNull = ST_GeogFromWKB(nullLiteral) + checkEvaluation(geographyExpressionNull, null) + // ST_GeogFromWKB with invalid WKB. + val invalidWkbLiteral = Literal.create(Array[Byte](111), BinaryType) + val geographyExpressionInvalidWkb = ST_GeogFromWKB(invalidWkbLiteral) + checkError( + exception = intercept[SparkIllegalArgumentException] { + geographyExpressionInvalidWkb.eval() + }, + condition = "WKB_PARSE_ERROR", + parameters = Map("parseError" -> "Unexpected end of WKB buffer", "pos" -> "0") + ) + } + test("ST_GeomFromWKB - expressions") { // Test data: WKB representation of POINT(1 2). val wkb = Hex.unhex("0101000000000000000000F03F0000000000000040".getBytes()) @@ -513,6 +538,16 @@ class STExpressionsSuite condition = "ST_INVALID_SRID_VALUE", parameters = Map("srid" -> s"$invalidSrid") ) + // ST_GeomFromWKB with invalid WKB. + val invalidWkbLiteral = Literal.create(Array[Byte](111), BinaryType) + val geometryExpressionInvalidWkb = new ST_GeomFromWKB(invalidWkbLiteral) + checkError( + exception = intercept[SparkIllegalArgumentException] { + geometryExpressionInvalidWkb.eval() + }, + condition = "WKB_PARSE_ERROR", + parameters = Map("parseError" -> "Unexpected end of WKB buffer", "pos" -> "0") + ) } test("ST_GeomFromWKB - columns") { diff --git a/sql/core/src/test/scala/org/apache/spark/sql/STFunctionsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/STFunctionsSuite.scala index dbde688de2645..1f52f2c0b9f58 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/STFunctionsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/STFunctionsSuite.scala @@ -17,6 +17,7 @@ package org.apache.spark.sql +import org.apache.spark.SparkIllegalArgumentException import org.apache.spark.sql.functions._ import org.apache.spark.sql.internal.SQLConf import org.apache.spark.sql.test.SharedSparkSession @@ -43,6 +44,27 @@ class STFunctionsSuite extends QueryTest with SharedSparkSession { "0101000000000000000000f03f0000000000000040")) } + test("st_geogfromwkb") { + // Test data: Well-Known Binary (WKB) representations. + val df = Seq[(String)]( + ( + "0101000000000000000000f03f0000000000000040" + )).toDF("wkb") + // ST_GeogFromWKB. + checkAnswer( + df.select(lower(hex(st_asbinary(st_geogfromwkb(unhex($"wkb"))))).as("col0")), + Row("0101000000000000000000f03f0000000000000040")) + // ST_GeogFromWKB with invalid WKB. + val df_invalid = Seq(Array[Byte](111)).toDF("wkb") + checkError( + exception = intercept[SparkIllegalArgumentException] { + df_invalid.select(st_geogfromwkb($"wkb")).collect() + }, + condition = "WKB_PARSE_ERROR", + parameters = Map("parseError" -> "Unexpected end of WKB buffer", "pos" -> "0") + ) + } + test("st_geomfromwkb") { // Test data: Well-Known Binary (WKB) representations. val df = Seq[(String, Int)]( @@ -59,6 +81,23 @@ class STFunctionsSuite extends QueryTest with SharedSparkSession { "0101000000000000000000f03f0000000000000040", "0101000000000000000000f03f0000000000000040", "0101000000000000000000f03f0000000000000040")) + // ST_GeomFromWKB with invalid SRID. + checkError( + exception = intercept[SparkIllegalArgumentException] { + df.select(st_geomfromwkb(unhex($"wkb"), lit(-1))).collect() + }, + condition = "ST_INVALID_SRID_VALUE", + parameters = Map("srid" -> "-1") + ) + // ST_GeomFromWKB with invalid WKB. + val df_invalid = Seq(Array[Byte](111)).toDF("wkb") + checkError( + exception = intercept[SparkIllegalArgumentException] { + df_invalid.select(st_geomfromwkb($"wkb")).collect() + }, + condition = "WKB_PARSE_ERROR", + parameters = Map("parseError" -> "Unexpected end of WKB buffer", "pos" -> "0") + ) } /** ST accessor expressions. */ From 1d5681382b9ea2b83bdd7533f59322b7b686145d Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Wed, 25 Feb 2026 21:21:48 -0800 Subject: [PATCH 051/130] [SPARK-55703][K8S][DOCS][INFRA] Upgrade Volcano to 1.14.1 ### What changes were proposed in this pull request? This PR aims to upgrade `Volcano` to 1.14.1 in K8s integration test document and GA job. ### Why are the changes needed? To use the latest version for testing and documentation for Apache Spark 4.2.0. - https://github.com/volcano-sh/volcano/releases/tag/v1.14.1 - https://github.com/volcano-sh/volcano/pull/5041 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Pass GA. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54502 from dongjoon-hyun/SPARK-55703. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- .github/workflows/build_and_test.yml | 2 +- docs/running-on-kubernetes.md | 4 ++-- resource-managers/kubernetes/integration-tests/README.md | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 6cc57ea0f52a8..4861d49739904 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -1464,7 +1464,7 @@ jobs: elif [[ "${{ inputs.branch }}" == 'branch-4.0' ]]; then kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.11.0/installer/volcano-development.yaml || true else - kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.14.0/installer/volcano-development.yaml || true + kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.14.1/installer/volcano-development.yaml || true fi eval $(minikube docker-env) build/sbt -Phadoop-3 -Psparkr -Pkubernetes -Pvolcano -Pkubernetes-integration-tests -Dspark.kubernetes.test.volcanoMaxConcurrencyJobNum=1 -Dtest.exclude.tags=local "kubernetes-integration-tests/test" diff --git a/docs/running-on-kubernetes.md b/docs/running-on-kubernetes.md index c1d50f3ecfb3e..34241555be5e1 100644 --- a/docs/running-on-kubernetes.md +++ b/docs/running-on-kubernetes.md @@ -1953,10 +1953,10 @@ Spark allows users to specify a custom Kubernetes schedulers. #### Using Volcano as Customized Scheduler for Spark on Kubernetes ##### Prerequisites -* Spark on Kubernetes with [Volcano](https://volcano.sh/en) as a custom scheduler is supported since Spark v3.3.0 and Volcano v1.7.0. Below is an example to install Volcano 1.14.0: +* Spark on Kubernetes with [Volcano](https://volcano.sh/en) as a custom scheduler is supported since Spark v3.3.0 and Volcano v1.7.0. Below is an example to install Volcano 1.14.1: ```bash - kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.14.0/installer/volcano-development.yaml + kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.14.1/installer/volcano-development.yaml ``` ##### Build diff --git a/resource-managers/kubernetes/integration-tests/README.md b/resource-managers/kubernetes/integration-tests/README.md index 8f50b9ca73546..a46996a85bac6 100644 --- a/resource-managers/kubernetes/integration-tests/README.md +++ b/resource-managers/kubernetes/integration-tests/README.md @@ -336,11 +336,11 @@ You can also specify your specific dockerfile to build JVM/Python/R based image ## Requirements - A minimum of 6 CPUs and 9G of memory is required to complete all Volcano test cases. -- Volcano v1.14.0. +- Volcano v1.14.1. ## Installation - kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.14.0/installer/volcano-development.yaml + kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.14.1/installer/volcano-development.yaml ## Run tests @@ -361,5 +361,5 @@ You can also specify `volcano` tag to only run Volcano test: ## Cleanup Volcano - kubectl delete -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.14.0/installer/volcano-development.yaml + kubectl delete -f https://raw.githubusercontent.com/volcano-sh/volcano/v1.14.1/installer/volcano-development.yaml From 778e43cb1c729d0f3320a7008d2edc4e838003ce Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Wed, 25 Feb 2026 22:12:51 -0800 Subject: [PATCH 052/130] [SPARK-55687][SQL][TEST] Fix ComputeCurrentTimeSuite - No duplicate literals on JDK 25 ### What changes were proposed in this pull request? Fix a test issue, see details at inline comments. ### Why are the changes needed? Fix a test issue that happens only on JDK 25. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? ``` $ export JAVA_HOME=/path/of/openjdk-25 $ build/sbt "catalyst/testOnly *ComputeCurrentTimeSuite" ``` before ``` [info] - No duplicate literals *** FAILED *** (17 milliseconds) [info] 28 did not equal 27 (ComputeCurrentTimeSuite.scala:262) [info] org.scalatest.exceptions.TestFailedException: [info] at org.scalatest.Assertions.newAssertionFailedException(Assertions.scala:472) [info] at org.scalatest.Assertions.newAssertionFailedException$(Assertions.scala:471) [info] at org.scalatest.Assertions$.newAssertionFailedException(Assertions.scala:1231) [info] at org.scalatest.Assertions$AssertionsHelper.macroAssert(Assertions.scala:1295) [info] at org.apache.spark.sql.catalyst.optimizer.ComputeCurrentTimeSuite.checkLiterals$1(ComputeCurrentTimeSuite.scala:262) [info] at org.apache.spark.sql.catalyst.optimizer.ComputeCurrentTimeSuite.$anonfun$new$23(ComputeCurrentTimeSuite.scala:267) ... [info] Run completed in 1 second, 623 milliseconds. [info] Total number of tests run: 13 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 12, failed 1, canceled 0, ignored 0, pending 0 [info] *** 1 TEST FAILED *** [error] Failed tests: [error] org.apache.spark.sql.catalyst.optimizer.ComputeCurrentTimeSuite [error] (catalyst / Test / testOnly) sbt.TestsFailedException: Tests unsuccessful [error] Total time: 29 s, completed Feb 25, 2026, 10:39:59 PM ``` after ``` ... [info] - No duplicate literals (13 milliseconds) [info] Run completed in 1 second, 742 milliseconds. [info] Total number of tests run: 13 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 13, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. [success] Total time: 16 s, completed Feb 25, 2026, 10:40:31 PM ``` ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54483 from pan3793/SPARK-55687. Authored-by: Cheng Pan Signed-off-by: Dongjoon Hyun --- .../catalyst/optimizer/ComputeCurrentTimeSuite.scala | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/ComputeCurrentTimeSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/ComputeCurrentTimeSuite.scala index 3fa6459a93e24..c4f71ec629573 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/ComputeCurrentTimeSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/ComputeCurrentTimeSuite.scala @@ -262,11 +262,15 @@ class ComputeCurrentTimeSuite extends PlanTest { assert(expected === uniqueLiteralObjectIds.size) } - val numTimezones = ZoneId.SHORT_IDS.size + // Use unique ZoneIds count instead of SHORT_IDS.size because some short zone IDs + // may map to the same ZoneId (e.g., in Java 25, MST and PNT both map to America/Phoenix) + val numUniqueZoneIds = ZoneId.SHORT_IDS.asScala.map { case (zoneId, _) => + ZoneId.of(zoneId, ZoneId.SHORT_IDS) + }.toSet.size checkLiterals({ _: String => CurrentTimestamp() }, 1) - checkLiterals({ zoneId: String => LocalTimestamp(Some(zoneId)) }, numTimezones) + checkLiterals({ zoneId: String => LocalTimestamp(Some(zoneId)) }, numUniqueZoneIds) checkLiterals({ _: String => Now() }, 1) - checkLiterals({ zoneId: String => CurrentDate(Some(zoneId)) }, numTimezones) + checkLiterals({ zoneId: String => CurrentDate(Some(zoneId)) }, numUniqueZoneIds) } private def literals[T](plan: LogicalPlan): scala.collection.mutable.ArrayBuffer[T] = { From 361ece3b9747d691486e505689e1115208c435d5 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Wed, 25 Feb 2026 23:23:09 -0800 Subject: [PATCH 053/130] [SPARK-55704][K8S] Add `Constants.DEFAULT_PVC_ACCESS_MODE` for reuse ### What changes were proposed in this pull request? This PR aims to add `Constants.DEFAULT_PVC_ACCESS_MODE` for reuse. ### Why are the changes needed? To allow the downstream projects like `Apache Spark K8s Operator` to reuse this constant. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Pass the CIs. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54503 from dongjoon-hyun/SPARK-55704. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- .../main/scala/org/apache/spark/deploy/k8s/Constants.scala | 1 + .../spark/deploy/k8s/features/MountVolumesFeatureStep.scala | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/Constants.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/Constants.scala index d9b3c3df945a3..4ffd617c4e4ce 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/Constants.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/Constants.scala @@ -105,6 +105,7 @@ object Constants { val KUBERNETES_MASTER_INTERNAL_URL = "https://kubernetes.default.svc" val DEFAULT_DRIVER_CONTAINER_NAME = "spark-kubernetes-driver" val DEFAULT_EXECUTOR_CONTAINER_NAME = "spark-kubernetes-executor" + val DEFAULT_PVC_ACCESS_MODE = "ReadWriteOncePod" val NON_JVM_MEMORY_OVERHEAD_FACTOR = 0.4d val CONNECT_GRPC_BINDING_PORT = "spark.connect.grpc.binding.port" val EXIT_EXCEPTION_ANNOTATION = "spark.exit-exception" diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/MountVolumesFeatureStep.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/MountVolumesFeatureStep.scala index 3d89696f19fcc..d851ba01cf68e 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/MountVolumesFeatureStep.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/MountVolumesFeatureStep.scala @@ -23,7 +23,7 @@ import io.fabric8.kubernetes.api.model._ import org.apache.spark.deploy.k8s._ import org.apache.spark.deploy.k8s.Config.KUBERNETES_USE_LEGACY_PVC_ACCESS_MODE -import org.apache.spark.deploy.k8s.Constants.{ENV_EXECUTOR_ID, SPARK_APP_ID_LABEL} +import org.apache.spark.deploy.k8s.Constants.{DEFAULT_PVC_ACCESS_MODE, ENV_EXECUTOR_ID, SPARK_APP_ID_LABEL} private[spark] class MountVolumesFeatureStep(conf: KubernetesConf) extends KubernetesFeatureConfigStep { @@ -33,7 +33,7 @@ private[spark] class MountVolumesFeatureStep(conf: KubernetesConf) val accessMode = if (conf.get(KUBERNETES_USE_LEGACY_PVC_ACCESS_MODE)) { "ReadWriteOnce" } else { - PVC_ACCESS_MODE + DEFAULT_PVC_ACCESS_MODE } override def configurePod(pod: SparkPod): SparkPod = { @@ -142,5 +142,4 @@ private[spark] object MountVolumesFeatureStep { val PVC_ON_DEMAND = "OnDemand" val PVC = "PersistentVolumeClaim" val PVC_POSTFIX = "-pvc" - val PVC_ACCESS_MODE = "ReadWriteOncePod" } From 811c3fa76428ffe01a45a55d7e35302fac4bf940 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Thu, 26 Feb 2026 18:14:22 +0800 Subject: [PATCH 054/130] [SPARK-55706][SQL][TESTS] Disable DB2 JDBC Driver tests ### What changes were proposed in this pull request? This PR aims to disable DB2 JDBC driver test coverage until it removes its side-effect. - `ConnectionProviderSuite` is revised to use another connection provider instead of `DB2`. - SPARK-55707 is filed to re-enable the disabled tests. ### Why are the changes needed? To avoid a side-effect on LZ4 test dependency. We had better focus on the non-test dependency first. ### Does this PR introduce _any_ user-facing change? No Spark's behavior change because this is only a test dependency and coverage. ### How was this patch tested? Pass the CIs. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54505 from dongjoon-hyun/SPARK-55706. Authored-by: Dongjoon Hyun Signed-off-by: Cheng Pan --- connector/docker-integration-tests/pom.xml | 5 +++-- .../spark/sql/jdbc/DB2IntegrationSuite.scala | 5 +++-- .../sql/jdbc/DB2KrbIntegrationSuite.scala | 2 ++ .../sql/jdbc/v2/DB2IntegrationSuite.scala | 5 +++-- .../spark/sql/jdbc/v2/DB2NamespaceSuite.scala | 6 +++++- pom.xml | 5 +++-- sql/core/pom.xml | 5 +++-- .../connection/ConnectionProviderSuite.scala | 20 +++++++++---------- .../DB2ConnectionProviderSuite.scala | 3 +++ .../org/apache/spark/sql/jdbc/JDBCSuite.scala | 10 +++++++--- 10 files changed, 42 insertions(+), 24 deletions(-) diff --git a/connector/docker-integration-tests/pom.xml b/connector/docker-integration-tests/pom.xml index e060de5c17f44..3c2234857814c 100644 --- a/connector/docker-integration-tests/pom.xml +++ b/connector/docker-integration-tests/pom.xml @@ -100,11 +100,12 @@ ojdbc17 test - + + com.microsoft.sqlserver mssql-jdbc diff --git a/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2IntegrationSuite.scala b/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2IntegrationSuite.scala index 6a489ffb2d42e..39aef6d7c90b3 100644 --- a/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2IntegrationSuite.scala +++ b/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2IntegrationSuite.scala @@ -21,12 +21,13 @@ import java.math.BigDecimal import java.sql.{Connection, Date, Timestamp} import java.util.Properties +import org.scalatest.Ignore + import org.apache.spark.sql.{Row, SaveMode} import org.apache.spark.sql.catalyst.util.CharVarcharUtils import org.apache.spark.sql.catalyst.util.DateTimeTestUtils._ import org.apache.spark.sql.internal.SQLConf import org.apache.spark.sql.types.{ByteType, ShortType, StructType} -import org.apache.spark.tags.DockerTest /** * To run this test suite for a specific version (e.g., icr.io/db2_community/db2:11.5.9.0): @@ -36,7 +37,7 @@ import org.apache.spark.tags.DockerTest * "docker-integration-tests/testOnly org.apache.spark.sql.jdbc.DB2IntegrationSuite" * }}} */ -@DockerTest +@Ignore // TODO(SPARK-55707): Re-enable DB2 JDBC Driver tests class DB2IntegrationSuite extends SharedJDBCIntegrationSuite { override val db = new DB2DatabaseOnDocker diff --git a/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2KrbIntegrationSuite.scala b/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2KrbIntegrationSuite.scala index c7d8fc43393ed..a34c1f5590a0d 100644 --- a/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2KrbIntegrationSuite.scala +++ b/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2KrbIntegrationSuite.scala @@ -24,6 +24,7 @@ import javax.security.auth.login.Configuration import com.github.dockerjava.api.model.{AccessMode, Bind, ContainerConfig, HostConfig, Volume} import org.apache.hadoop.security.{SecurityUtil, UserGroupInformation} import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod.KERBEROS +import org.scalatest.Ignore import org.apache.spark.sql.execution.datasources.jdbc.JDBCOptions import org.apache.spark.sql.execution.datasources.jdbc.connection.{DB2ConnectionProvider, SecureConnectionProvider} @@ -37,6 +38,7 @@ import org.apache.spark.tags.DockerTest * "docker-integration-tests/testOnly *DB2KrbIntegrationSuite" * }}} */ +@Ignore // TODO(SPARK-55707: Re-enable DB2 JDBC Driver tests) @DockerTest class DB2KrbIntegrationSuite extends DockerKrbJDBCIntegrationSuite { override protected val userName = s"db2/$dockerIp" diff --git a/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/v2/DB2IntegrationSuite.scala b/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/v2/DB2IntegrationSuite.scala index ecc02f7051787..e0b937a61fecb 100644 --- a/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/v2/DB2IntegrationSuite.scala +++ b/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/v2/DB2IntegrationSuite.scala @@ -20,12 +20,13 @@ package org.apache.spark.sql.jdbc.v2 import java.sql.Connection import java.util.Locale +import org.scalatest.Ignore + import org.apache.spark.SparkConf import org.apache.spark.sql.AnalysisException import org.apache.spark.sql.execution.datasources.v2.jdbc.JDBCTableCatalog import org.apache.spark.sql.jdbc.DB2DatabaseOnDocker import org.apache.spark.sql.types._ -import org.apache.spark.tags.DockerTest /** * To run this test suite for a specific version (e.g., icr.io/db2_community/db2:11.5.9.0): @@ -34,7 +35,7 @@ import org.apache.spark.tags.DockerTest * ./build/sbt -Pdocker-integration-tests "testOnly *v2.DB2IntegrationSuite" * }}} */ -@DockerTest +@Ignore // TODO(SPARK-55707): Re-enable DB2 JDBC Driver tests class DB2IntegrationSuite extends DockerJDBCIntegrationV2Suite with V2JDBCTest { // Following tests are disabled for both single and multiple partition read diff --git a/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/v2/DB2NamespaceSuite.scala b/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/v2/DB2NamespaceSuite.scala index 385039fb6bd51..f932727377de0 100644 --- a/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/v2/DB2NamespaceSuite.scala +++ b/connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/v2/DB2NamespaceSuite.scala @@ -21,6 +21,8 @@ import java.sql.Connection import scala.jdk.CollectionConverters._ +import org.scalatest.Ignore + import org.apache.spark.sql.jdbc.{DB2DatabaseOnDocker, DockerJDBCIntegrationSuite} import org.apache.spark.sql.util.CaseInsensitiveStringMap import org.apache.spark.tags.DockerTest @@ -32,6 +34,7 @@ import org.apache.spark.tags.DockerTest * ./build/sbt -Pdocker-integration-tests "testOnly *v2.DB2NamespaceSuite" * }}} */ +@Ignore // TODO(SPARK-55707): Re-enable DB2 JDBC Driver tests @DockerTest class DB2NamespaceSuite extends DockerJDBCIntegrationSuite with V2JDBCNamespaceTest { override val db = new DB2DatabaseOnDocker @@ -39,7 +42,8 @@ class DB2NamespaceSuite extends DockerJDBCIntegrationSuite with V2JDBCNamespaceT Map("url" -> db.getJdbcUrl(dockerIp, externalPort), "driver" -> "com.ibm.db2.jcc.DB2Driver").asJava) - catalog.initialize("db2", map) + // TODO(SPARK-55707): Re-enable DB2 JDBC Driver tests + // catalog.initialize("db2", map) override def dataPreparation(conn: Connection): Unit = {} diff --git a/pom.xml b/pom.xml index 0c46c13871f15..b7b43ab03c8e8 100644 --- a/pom.xml +++ b/pom.xml @@ -1357,12 +1357,13 @@ ${postgresql.version} test - + + com.microsoft.sqlserver mssql-jdbc diff --git a/sql/core/pom.xml b/sql/core/pom.xml index bddc7790594e2..18956310a0828 100644 --- a/sql/core/pom.xml +++ b/sql/core/pom.xml @@ -206,11 +206,12 @@ postgresql test - + + com.ibm.icu icu4j diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProviderSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProviderSuite.scala index 0d7b133f0e15e..b2e788b52109e 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProviderSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProviderSuite.scala @@ -185,28 +185,28 @@ class ConnectionProviderSuite val postgresDriver = registerDriver(postgresProvider.driverClass) val postgresOptions = options("jdbc:postgresql://localhost/postgres") val postgresAppEntry = postgresProvider.appEntry(postgresDriver, postgresOptions) - val db2Provider = new DB2ConnectionProvider() - val db2Driver = registerDriver(db2Provider.driverClass) - val db2Options = options("jdbc:db2://localhost/db2") - val db2AppEntry = db2Provider.appEntry(db2Driver, db2Options) + val mysqlProvider = new MariaDBConnectionProvider() + val mysqlDriver = registerDriver(mysqlProvider.driverClass) + val mysqlOptions = options("jdbc:mysql://localhost/db") + val mysqlAppEntry = mysqlProvider.appEntry(mysqlDriver, mysqlOptions) // Make sure no authentication for the databases are set val rootConfig = Configuration.getConfiguration assert(rootConfig.getAppConfigurationEntry(postgresAppEntry) == null) - assert(rootConfig.getAppConfigurationEntry(db2AppEntry) == null) + assert(rootConfig.getAppConfigurationEntry(mysqlAppEntry) == null) postgresProvider.setAuthenticationConfig(postgresDriver, postgresOptions) val postgresConfig = Configuration.getConfiguration - db2Provider.setAuthenticationConfig(db2Driver, db2Options) - val db2Config = Configuration.getConfiguration + mysqlProvider.setAuthenticationConfig(mysqlDriver, mysqlOptions) + val mysqlConfig = Configuration.getConfiguration // Make sure authentication for the databases are set assert(rootConfig != postgresConfig) - assert(rootConfig != db2Config) + assert(rootConfig != mysqlConfig) // The topmost config in the chain is linked with all the subsequent entries - assert(db2Config.getAppConfigurationEntry(postgresAppEntry) != null) - assert(db2Config.getAppConfigurationEntry(db2AppEntry) != null) + assert(mysqlConfig.getAppConfigurationEntry(postgresAppEntry) != null) + assert(mysqlConfig.getAppConfigurationEntry(mysqlAppEntry) != null) Configuration.setConfiguration(null) } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/DB2ConnectionProviderSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/DB2ConnectionProviderSuite.scala index 895b3d85d960b..f29a1b1e7ab62 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/DB2ConnectionProviderSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/DB2ConnectionProviderSuite.scala @@ -17,6 +17,9 @@ package org.apache.spark.sql.execution.datasources.jdbc.connection +import org.scalatest.Ignore + +@Ignore // TODO(SPARK-55707): Re-enable DB2 JDBC Driver tests class DB2ConnectionProviderSuite extends ConnectionProviderSuiteBase { test("setAuthenticationConfig must set authentication all the time") { val provider = new DB2ConnectionProvider() diff --git a/sql/core/src/test/scala/org/apache/spark/sql/jdbc/JDBCSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/jdbc/JDBCSuite.scala index e38648e9468ca..3268d532a34cd 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/jdbc/JDBCSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/jdbc/JDBCSuite.scala @@ -1088,7 +1088,8 @@ class JDBCSuite extends QueryTest with SharedSparkSession { "SELECT TOP (123) a,b FROM test") } - test("SPARK-42534: DB2Dialect Limit query test") { + // TODO(SPARK-55707): Re-enable DB2 JDBC Driver tests + ignore("SPARK-42534: DB2Dialect Limit query test") { // JDBC url is a required option but is not used in this test. val options = new JDBCOptions(Map("url" -> "jdbc:db2://host:port", "dbtable" -> "test")) assert( @@ -2261,7 +2262,9 @@ class JDBCSuite extends QueryTest with SharedSparkSession { } // not supported Seq( - "jdbc:db2://host:port", "jdbc:derby:memory", "jdbc:h2://host:port", + // TODO(SPARK-55707): Re-enable DB2 JDBC Driver tests + // "jdbc:db2://host:port", + "jdbc:derby:memory", "jdbc:h2://host:port", "jdbc:sqlserver://host:port", "jdbc:postgresql://host:5432/postgres", "jdbc:snowflake://host:443?account=test", "jdbc:teradata://host:port").foreach { url => val options = new JDBCOptions(baseParameters + ("url" -> url)) @@ -2282,7 +2285,8 @@ class JDBCSuite extends QueryTest with SharedSparkSession { "jdbc:mysql", "jdbc:postgresql", "jdbc:sqlserver", - "jdbc:db2", + // TODO(SPARK-55707): Re-enable DB2 JDBC Driver tests + // "jdbc:db2", "jdbc:h2", "jdbc:teradata", "jdbc:databricks" From ee467ff3f191b2d570b93a8a5fe581de857dffc1 Mon Sep 17 00:00:00 2001 From: Kent Yao Date: Thu, 26 Feb 2026 18:41:05 +0800 Subject: [PATCH 055/130] [SPARK-55711][UI][FOLLOWUP] Fix Job DAG visualization display issue caused by initial viewBox ### What changes were proposed in this pull request? Follow-up to SPARK-54373 (#53087). Replace the initial `viewBox` attribute with `width` and `height` on the Job DAG SVG element, consistent with the fix applied to `spark-sql-viz.js` in the SPARK-54374 followup (#54482). ### Why are the changes needed? Setting `viewBox` before dagre-d3 renders the graph changes the SVG coordinate system, which affects how dagre-d3 positions elements. This causes the same display issue as reported for SQL plan visualization in https://github.com/apache/spark/pull/53864#issuecomment-3889339344. Using `width` and `height` instead gives a large initial canvas without altering the coordinate system that dagre-d3 depends on. The final `viewBox`, `width`, and `height` are still correctly set after rendering completes. ### Does this PR introduce _any_ user-facing change? Yes, fixes the Job DAG visualization display regression introduced by SPARK-54373. ### How was this patch tested? Tested in Chrome DevTools. ### Was this patch authored or co-authored using generative AI tooling? Yes, GitHub Copilot CLI was used. cc pan3793 Closes #54511 from yaooqinn/SPARK-55711. Authored-by: Kent Yao Signed-off-by: Cheng Pan --- .../main/resources/org/apache/spark/ui/static/spark-dag-viz.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js b/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js index 9deeb419d3ec9..fa30004bb5b7b 100644 --- a/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js +++ b/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js @@ -160,7 +160,8 @@ function renderDagViz(forJob) { const svg = graphContainer() .append("svg") .attr("class", jobOrStage) - .attr("viewBox", `${-VizConstants.svgMarginX} ${-VizConstants.svgMarginY} ${window.innerWidth || 1920} 1000`); + .attr("width", window.innerWidth || 1920) + .attr("height", 1000); if (forJob) { renderDagVizForJob(svg); } else { From 1b99a561c8e2afdbb3af5933e227b81ae44cfd1a Mon Sep 17 00:00:00 2001 From: Uros Bojanic Date: Thu, 26 Feb 2026 19:03:44 +0800 Subject: [PATCH 056/130] [SPARK-55539][GEO][SQL] Allow casting from GeographyType to GeometryType ### What changes were proposed in this pull request? This PR allows casting `GEOMETRY` to `GEOGRAPHY` if they have the same geographic SRID. ### Why are the changes needed? Enable explicit casting between geospatial types. ### Does this PR introduce _any_ user-facing change? Yes, casting `GEOMETRY` to `GEOGRAPHY` is now allowed. ### How was this patch tested? Added new unit tests: - `StUtilsSuite` - `CastSuiteBase` Added new e2e SQL tests: - `st-functions` ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54331 from uros-db/geo-cast-geom_geog. Authored-by: Uros Bojanic Signed-off-by: Wenchen Fan --- .../spark/sql/catalyst/util/STUtils.java | 19 ++++++++ .../spark/sql/catalyst/expressions/Cast.scala | 31 ++++++++++-- .../catalyst/expressions/CastSuiteBase.scala | 32 +++++++++++++ .../spark/sql/catalyst/util/StUtilsSuite.java | 30 ++++++++++++ .../analyzer-results/st-functions.sql.out | 36 ++++++++++++++ .../sql-tests/inputs/st-functions.sql | 7 +++ .../sql-tests/results/st-functions.sql.out | 48 +++++++++++++++++++ 7 files changed, 200 insertions(+), 3 deletions(-) diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/STUtils.java b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/STUtils.java index c02192965fd7c..4026bbb2c22df 100644 --- a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/STUtils.java +++ b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/util/STUtils.java @@ -16,6 +16,8 @@ */ package org.apache.spark.sql.catalyst.util; +import org.apache.spark.sql.catalyst.util.geo.WkbParseException; +import org.apache.spark.sql.catalyst.util.geo.WkbReader; import org.apache.spark.sql.errors.QueryExecutionErrors; import org.apache.spark.sql.types.GeographyType; import org.apache.spark.sql.types.GeometryType; @@ -52,6 +54,23 @@ static GeometryVal toPhysVal(Geometry g) { /** Geospatial type casting utility methods. */ + // Cast geometry to geography. + public static GeographyVal geometryToGeography(GeometryVal geometryVal) { + // We first need to check whether the input geometry has a geographic SRID. + int srid = stSrid(geometryVal); + if(!GeographyType.isSridSupported(srid)) { + throw QueryExecutionErrors.stInvalidSridValueError(String.valueOf(srid)); + } + // We also need to check whether the input geometry has coordinates in geography bounds. + try { + byte[] wkb = stAsBinary(geometryVal); + new WkbReader(true).read(wkb, srid); + } catch (WkbParseException e) { + throw QueryExecutionErrors.wkbParseError(e.getParseError(), e.getPosition()); + } + return toPhysVal(Geography.fromBytes(geometryVal.getBytes())); + } + // Cast geography to geometry. public static GeometryVal geographyToGeometry(GeographyVal geographyVal) { // Geographic SRID is always a valid SRID for geometry, so we don't need to check it. diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala index 849f3b8a0d1bf..c51d3508d04a4 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala @@ -38,7 +38,7 @@ import org.apache.spark.sql.catalyst.util.IntervalUtils.{dayTimeIntervalToByte, import org.apache.spark.sql.errors.{QueryErrorsBase, QueryExecutionErrors} import org.apache.spark.sql.internal.SQLConf import org.apache.spark.sql.types._ -import org.apache.spark.unsafe.types.{GeographyVal, UTF8String, VariantVal} +import org.apache.spark.unsafe.types.{GeographyVal, GeometryVal, UTF8String, VariantVal} import org.apache.spark.unsafe.types.UTF8String.{IntWrapper, LongWrapper} import org.apache.spark.util.ArrayImplicits._ @@ -173,6 +173,9 @@ object Cast extends QueryErrorsBase { // Casts from concrete GEOMETRY(srid) to mixed GEOMETRY(ANY) is allowed. case (gt1: GeometryType, gt2: GeometryType) if !gt1.isMixedSrid && gt2.isMixedSrid => true + // Casting from GEOMETRY to GEOGRAPHY with the same SRID is allowed. + case (geom: GeometryType, geog: GeographyType) if geom.srid == geog.srid => + true case _ => false } @@ -309,6 +312,9 @@ object Cast extends QueryErrorsBase { // Casts from concrete GEOMETRY(srid) to mixed GEOMETRY(ANY) is allowed. case (gt1: GeometryType, gt2: GeometryType) if !gt1.isMixedSrid && gt2.isMixedSrid => true + // Casting from GEOMETRY to GEOGRAPHY with the same SRID is allowed. + case (geom: GeometryType, geog: GeographyType) if geom.srid == geog.srid => + true case _ => false } @@ -1200,6 +1206,14 @@ case class Cast( b => numeric.toFloat(b) } + // GeographyConverter + private[this] def castToGeography(from: DataType): Any => Any = from match { + case _: GeographyType => + identity + case _: GeometryType => + buildCast[GeometryVal](_, STUtils.geometryToGeography) + } + // GeometryConverter private[this] def castToGeometry(from: DataType): Any => Any = from match { case _: GeographyType => @@ -1287,7 +1301,7 @@ case class Cast( case FloatType => castToFloat(from) case LongType => castToLong(from) case DoubleType => castToDouble(from) - case _: GeographyType => identity + case _: GeographyType => castToGeography(from) case _: GeometryType => castToGeometry(from) case array: ArrayType => castArray(from.asInstanceOf[ArrayType].elementType, array.elementType) @@ -1397,7 +1411,7 @@ case class Cast( case FloatType => castToFloatCode(from, ctx) case LongType => castToLongCode(from, ctx) case DoubleType => castToDoubleCode(from, ctx) - case _: GeographyType => (c, evPrim, _) => code"$evPrim = $c;" + case _: GeographyType => castToGeographyCode(from) case _: GeometryType => castToGeometryCode(from) case array: ArrayType => @@ -2245,6 +2259,17 @@ case class Cast( } } + private[this] def castToGeographyCode(from: DataType): CastFunction = { + from match { + case _: GeographyType => + (c, evPrim, _) => + code"$evPrim = $c;" + case _: GeometryType => + (c, evPrim, _) => + code"$evPrim = org.apache.spark.sql.catalyst.util.STUtils.geometryToGeography($c);" + } + } + private[this] def castToGeometryCode(from: DataType): CastFunction = { from match { case _: GeographyType => diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastSuiteBase.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastSuiteBase.scala index e18a489d36f3b..e888432ef91eb 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastSuiteBase.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastSuiteBase.scala @@ -1544,6 +1544,38 @@ abstract class CastSuiteBase extends SparkFunSuite with ExpressionEvalHelper { } } + test("Casting GeometryType to GeographyType") { + // Casting from GEOMETRY to GEOGRAPHY is only allowed if the SRIDs are the same. + + // Valid cast test cases. + val canAnsiCastTestCases: Seq[(DataType, DataType)] = Seq( + (GeometryType(4326), GeographyType(4326)), + (GeometryType("ANY"), GeographyType("ANY")) + ) + // Iterate over the test cases and verify casting. + canAnsiCastTestCases.foreach { case (fromType, toType) => + // Cast can be performed from `fromType` to `toType`. + assert(Cast.canCast(fromType, toType)) + assert(Cast.canAnsiCast(fromType, toType)) + } + + // Invalid cast test cases. + val cannotAnsiCastTestCases: Seq[(DataType, DataType)] = Seq( + (GeometryType(0), GeographyType(4326)), + (GeometryType(3857), GeographyType(4326)), + (GeometryType("ANY"), GeographyType(4326)), + (GeometryType(0), GeographyType("ANY")), + (GeometryType(3857), GeographyType("ANY")), + (GeometryType(4326), GeographyType("ANY")) + ) + // Iterate over the test cases and verify casting. + cannotAnsiCastTestCases.foreach { case (fromType, toType) => + // Cast cannot be performed from `fromType` to `toType`. + assert(!Cast.canCast(fromType, toType)) + assert(!Cast.canAnsiCast(fromType, toType)) + } + } + test("Casting GeometryType to GeometryType") { // Casting from fixed SRID GEOMETRY() to mixed SRID GEOMETRY(ANY) is always allowed. // Type casting is always safe in this direction, so no additional constraints are imposed. diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/StUtilsSuite.java b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/StUtilsSuite.java index e5e6d32ab99f8..aa1b4735cf62f 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/StUtilsSuite.java +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/StUtilsSuite.java @@ -45,6 +45,7 @@ class STUtilsSuite { // A sample Geometry byte array for testing purposes, representing a POINT(1 2) with SRID 0. private final int testGeometrySrid = 0; private final byte[] testGeometryBytes; + private final byte[] testGeometry4326Bytes; // Common constants used in geo value construction. private final ByteOrder end = Geo.DEFAULT_ENDIANNESS; @@ -63,10 +64,39 @@ class STUtilsSuite { testGeometryBytes = new byte[sridLen + wkbLen]; System.arraycopy(geomSrid, 0, testGeometryBytes, 0, sridLen); System.arraycopy(testWkb, 0, testGeometryBytes, sridLen, wkbLen); + testGeometry4326Bytes = new byte[sridLen + wkbLen]; + System.arraycopy(geogSrid, 0, testGeometry4326Bytes, 0, sridLen); + System.arraycopy(testWkb, 0, testGeometry4326Bytes, sridLen, wkbLen); } /** Geospatial type casting utility methods. */ + @Test + void testGeometryToGeography() { + GeometryVal geometryVal = GeometryVal.fromBytes(testGeometry4326Bytes); + GeographyVal geographyVal = STUtils.geometryToGeography(geometryVal); + assertNotNull(geographyVal); + assertArrayEquals(geometryVal.getBytes(), geographyVal.getBytes()); + // Non-geographic SRID should not be allowed for geometry to geography casting. + SparkIllegalArgumentException sridException = assertThrows( + SparkIllegalArgumentException.class, + () -> STUtils.geometryToGeography(GeometryVal.fromBytes(testGeometryBytes))); + assertEquals("ST_INVALID_SRID_VALUE", sridException.getCondition()); + // Coordinates outside geography bounds should not be allowed even with a valid SRID. + ByteBuffer oobWkbBuf = ByteBuffer.allocate(21).order(ByteOrder.LITTLE_ENDIAN); + oobWkbBuf.put((byte) 0x01).putInt(1).putDouble(200.0).putDouble(100.0); + // For example: POINT(200 100) geometry with SRID 4326. + byte[] oobWkb = oobWkbBuf.array(); + byte[] oobGeomBytes = new byte[sridLen + oobWkb.length]; + byte[] srid4326 = ByteBuffer.allocate(sridLen).order(end).putInt(testGeographySrid).array(); + System.arraycopy(srid4326, 0, oobGeomBytes, 0, sridLen); + System.arraycopy(oobWkb, 0, oobGeomBytes, sridLen, oobWkb.length); + SparkIllegalArgumentException coordinateException = assertThrows( + SparkIllegalArgumentException.class, + () -> STUtils.geometryToGeography(GeometryVal.fromBytes(oobGeomBytes))); + assertEquals("WKB_PARSE_ERROR", coordinateException.getCondition()); + } + @Test void testGeographyToGeometry() { GeographyVal geographyVal = GeographyVal.fromBytes(testGeographyBytes); diff --git a/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out b/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out index 7566e69392fdc..34969f43e1f73 100644 --- a/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out +++ b/sql/core/src/test/resources/sql-tests/analyzer-results/st-functions.sql.out @@ -308,6 +308,42 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException } +-- !query +SELECT hex(ST_AsBinary(CAST(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040', 4326) AS GEOGRAPHY(4326)))) AS result +-- !query analysis +Project [hex(st_asbinary(cast(st_geomfromwkb(0x0101000000000000000000F03F0000000000000040, 4326) as geography(4326)))) AS result#x] ++- OneRowRelation + + +-- !query +SELECT CAST(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040') AS GEOGRAPHY(4326)) AS result +-- !query analysis +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "DATATYPE_MISMATCH.CAST_WITHOUT_SUGGESTION", + "sqlState" : "42K09", + "messageParameters" : { + "sqlExpr" : "\"CAST(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040', 0) AS GEOGRAPHY(4326))\"", + "srcType" : "\"GEOMETRY(0)\"", + "targetType" : "\"GEOGRAPHY(4326)\"" + }, + "queryContext" : [ { + "objectType" : "", + "objectName" : "", + "startIndex" : 8, + "stopIndex" : 93, + "fragment" : "CAST(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040') AS GEOGRAPHY(4326))" + } ] +} + + +-- !query +SELECT CAST(ST_GeomFromWKB(X'010100000000000000000069400000000000005940', 4326) AS GEOGRAPHY(4326)) AS result +-- !query analysis +Project [cast(st_geomfromwkb(0x010100000000000000000069400000000000005940, 4326) as geography(4326)) AS result#x] ++- OneRowRelation + + -- !query SELECT typeof(array(ST_GeogFromWKB(wkb), ST_GeogFromWKB(wkb)::GEOGRAPHY(ANY))) FROM geodata -- !query analysis diff --git a/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql b/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql index f3543837ddfc3..0db835bc7e85d 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/st-functions.sql @@ -58,6 +58,13 @@ SELECT hex(ST_AsBinary(CAST(ST_GeomFromWKB(X'0101000000000000000000f03f000000000 -- Casting GEOMETRY(ANY) to GEOMETRY() is not allowed. SELECT CAST(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040')::GEOMETRY(ANY) AS GEOMETRY(4326)) AS result; +-- Casting GEOMETRY to GEOGRAPHY is allowed only if SRIDs match. +SELECT hex(ST_AsBinary(CAST(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040', 4326) AS GEOGRAPHY(4326)))) AS result; +-- Error handling: mismatched SRIDs. +SELECT CAST(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040') AS GEOGRAPHY(4326)) AS result; +-- Error handling: coordinates out of geographic bounds. +SELECT CAST(ST_GeomFromWKB(X'010100000000000000000069400000000000005940', 4326) AS GEOGRAPHY(4326)) AS result; + ---- Geospatial type coercion -- Array diff --git a/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out b/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out index 03f5728d7d3a6..11ca99bc23047 100644 --- a/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/st-functions.sql.out @@ -345,6 +345,54 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException } +-- !query +SELECT hex(ST_AsBinary(CAST(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040', 4326) AS GEOGRAPHY(4326)))) AS result +-- !query schema +struct +-- !query output +0101000000000000000000F03F0000000000000040 + + +-- !query +SELECT CAST(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040') AS GEOGRAPHY(4326)) AS result +-- !query schema +struct<> +-- !query output +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "DATATYPE_MISMATCH.CAST_WITHOUT_SUGGESTION", + "sqlState" : "42K09", + "messageParameters" : { + "sqlExpr" : "\"CAST(st_geomfromwkb(X'0101000000000000000000F03F0000000000000040', 0) AS GEOGRAPHY(4326))\"", + "srcType" : "\"GEOMETRY(0)\"", + "targetType" : "\"GEOGRAPHY(4326)\"" + }, + "queryContext" : [ { + "objectType" : "", + "objectName" : "", + "startIndex" : 8, + "stopIndex" : 93, + "fragment" : "CAST(ST_GeomFromWKB(X'0101000000000000000000f03f0000000000000040') AS GEOGRAPHY(4326))" + } ] +} + + +-- !query +SELECT CAST(ST_GeomFromWKB(X'010100000000000000000069400000000000005940', 4326) AS GEOGRAPHY(4326)) AS result +-- !query schema +struct<> +-- !query output +org.apache.spark.SparkIllegalArgumentException +{ + "errorClass" : "WKB_PARSE_ERROR", + "sqlState" : "22023", + "messageParameters" : { + "parseError" : "Invalid coordinate value found", + "pos" : "5" + } +} + + -- !query SELECT typeof(array(ST_GeogFromWKB(wkb), ST_GeogFromWKB(wkb)::GEOGRAPHY(ANY))) FROM geodata -- !query schema From 02453b101a8c2d5cd671116032a1677fe4191bec Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Thu, 26 Feb 2026 19:14:44 +0800 Subject: [PATCH 057/130] [SPARK-55712][INFRA] Allow run benchmark with JDK 25 ### What changes were proposed in this pull request? As title. ### Why are the changes needed? To enable Java 25 support. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Review. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54512 from pan3793/SPARK-55712. Authored-by: Cheng Pan Signed-off-by: Cheng Pan --- .github/workflows/benchmark.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index c45796850d8b8..1341f2c3ffad5 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -28,12 +28,13 @@ on: default: '*' jdk: type: choice - description: 'JDK version: 17 or 21' + description: 'JDK version: 17, 21, or 25' required: true default: '17' options: - '17' - '21' + - '25' scala: type: choice description: 'Scala version: 2.13' From 7742e73cac49e6e2321f86fdcaf1472f6a006d1b Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Thu, 26 Feb 2026 08:29:03 -0800 Subject: [PATCH 058/130] [SPARK-55709][K8S][TESTS] Fix `ExecutorLifecycleTestUtils.persistentVolumeClaim` to use `ReadWriteOncePod` instead of `ReadWriteOnce` ### What changes were proposed in this pull request? This PR aims to fix `ExecutorLifecycleTestUtils.persistentVolumeClaim` to use `ReadWriteOncePod` instead of `ReadWriteOnce`. ### Why are the changes needed? Since Apache Spark 4.0.0, we used `ReadWriteOncePod` by default. We should test the Apache Spark's behavior consistently. - #44817 - #44985 ### Does this PR introduce _any_ user-facing change? No, this is a test case change. ### How was this patch tested? Pass the CIs. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54507 from dongjoon-hyun/SPARK-55709. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- .../scheduler/cluster/k8s/ExecutorLifecycleTestUtils.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorLifecycleTestUtils.scala b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorLifecycleTestUtils.scala index fc75414e4a7e0..272f41f30b580 100644 --- a/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorLifecycleTestUtils.scala +++ b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorLifecycleTestUtils.scala @@ -260,7 +260,7 @@ object ExecutorLifecycleTestUtils { .endMetadata() .withNewSpec() .withStorageClassName(storageClass) - .withAccessModes("ReadWriteOnce") + .withAccessModes(DEFAULT_PVC_ACCESS_MODE) .withResources(new VolumeResourceRequirementsBuilder() .withRequests(Map("storage" -> new Quantity(size)).asJava).build()) .endSpec() From 366550689fc79d863e8bf8ae60ca994acaffe49c Mon Sep 17 00:00:00 2001 From: Peter Toth Date: Thu, 26 Feb 2026 08:59:18 -0800 Subject: [PATCH 059/130] [SPARK-55692][SQL] Fix `SupportsRuntimeFiltering` and `SupportsRuntimeV2Filtering` documentation ### What changes were proposed in this pull request? This is a follow-up to https://github.com/apache/spark/pull/38924 clarify behaviour of scans with runtime filters. ### Why are the changes needed? Please see discussion at https://github.com/apache/spark/pull/54330#discussion_r2847645387. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? This is a documentation change. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54490 from peter-toth/SPARK-55692-fix-supportsruntimefiltering-docs. Authored-by: Peter Toth Signed-off-by: Dongjoon Hyun --- .../sql/connector/read/SupportsRuntimeFiltering.java | 9 +++++---- .../sql/connector/read/SupportsRuntimeV2Filtering.java | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeFiltering.java b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeFiltering.java index 0921a90ac22a7..927d4a53e22fc 100644 --- a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeFiltering.java +++ b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeFiltering.java @@ -49,10 +49,11 @@ public interface SupportsRuntimeFiltering extends SupportsRuntimeV2Filtering { *

* If the scan also implements {@link SupportsReportPartitioning}, it must preserve * the originally reported partitioning during runtime filtering. While applying runtime filters, - * the scan may detect that some {@link InputPartition}s have no matching data. It can omit - * such partitions entirely only if it does not report a specific partitioning. Otherwise, - * the scan can replace the initially planned {@link InputPartition}s that have no matching - * data with empty {@link InputPartition}s but must preserve the overall number of partitions. + * the scan may detect that some {@link InputPartition}s have no matching data, in which case + * it can either replace the initially planned {@link InputPartition}s that have no matching data + * with empty {@link InputPartition}s, or report only a subset of the original partition values + * (omitting those with no data) via {@link Batch#planInputPartitions()}. The scan must not report + * new partition values that were not present in the original partitioning. *

* Note that Spark will call {@link Scan#toBatch()} again after filtering the scan at runtime. * diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeV2Filtering.java b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeV2Filtering.java index 7c238bde969b2..f5acdf885bf5c 100644 --- a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeV2Filtering.java +++ b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/SupportsRuntimeV2Filtering.java @@ -53,11 +53,11 @@ public interface SupportsRuntimeV2Filtering extends Scan { *

* If the scan also implements {@link SupportsReportPartitioning}, it must preserve * the originally reported partitioning during runtime filtering. While applying runtime - * predicates, the scan may detect that some {@link InputPartition}s have no matching data. It - * can omit such partitions entirely only if it does not report a specific partitioning. - * Otherwise, the scan can replace the initially planned {@link InputPartition}s that have no - * matching data with empty {@link InputPartition}s but must preserve the overall number of - * partitions. + * predicates, the scan may detect that some {@link InputPartition}s have no matching data, in + * which case it can either replace the initially planned {@link InputPartition}s that have no + * matching data with empty {@link InputPartition}s, or report only a subset of the original + * partition values (omitting those with no data) via {@link Batch#planInputPartitions()}. The + * scan must not report new partition values that were not present in the original partitioning. *

* Note that Spark will call {@link Scan#toBatch()} again after filtering the scan at runtime. * From baa850762e2da619a9515f985f536d27895ec1a3 Mon Sep 17 00:00:00 2001 From: Kent Yao Date: Thu, 26 Feb 2026 09:03:04 -0800 Subject: [PATCH 060/130] [SPARK-55710][BUILD] Use Google Mirror of Maven Central for SBT bootstrap ### What changes were proposed in this pull request? Change the default SBT bootstrap repository from Maven Central (`repo1.maven.org`) to Google's Maven Central mirror (`maven-central.storage-download.googleapis.com`) for downloading the `sbt-launch` jar. ### Why are the changes needed? The rest of the SBT build already uses the Google mirror as the primary resolver, as `project/SparkBuild.scala`. The bootstrap script (`build/sbt-launch-lib.bash`) was the only place still defaulting to Maven Central. This makes it consistent and avoids flaky Maven Central connections during the initial `sbt-launch` jar download. The `DEFAULT_ARTIFACT_REPOSITORY` environment variable can still be used to override this. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Manually tested by removing the cached `sbt-launch-1.12.4.jar` and verifying the bootstrap successfully downloads from the Google mirror with matching checksum. ### Was this patch authored or co-authored using generative AI tooling? Yes, GitHub Copilot CLI was used. Closes #54508 from yaooqinn/SPARK-55710. Authored-by: Kent Yao Signed-off-by: Dongjoon Hyun --- build/sbt-launch-lib.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/sbt-launch-lib.bash b/build/sbt-launch-lib.bash index 01ba6b929f922..713f88e082990 100755 --- a/build/sbt-launch-lib.bash +++ b/build/sbt-launch-lib.bash @@ -43,7 +43,7 @@ acquire_sbt_jar () { # artifacts from internal repos only. # Ex: # DEFAULT_ARTIFACT_REPOSITORY=https://artifacts.internal.com/libs-release/ - URL1=${DEFAULT_ARTIFACT_REPOSITORY:-https://repo1.maven.org/maven2/}org/scala-sbt/sbt-launch/${SBT_VERSION}/sbt-launch-${SBT_VERSION}.jar + URL1=${DEFAULT_ARTIFACT_REPOSITORY:-https://maven-central.storage-download.googleapis.com/maven2/}org/scala-sbt/sbt-launch/${SBT_VERSION}/sbt-launch-${SBT_VERSION}.jar JAR=build/sbt-launch-${SBT_VERSION}.jar sbt_jar=$JAR From c15e36b70b7c72909a46ad32006a3cf5a6ee0c1c Mon Sep 17 00:00:00 2001 From: Ruifeng Zheng Date: Thu, 26 Feb 2026 09:05:40 -0800 Subject: [PATCH 061/130] [SPARK-55705][PYTHON][INFRA] Upgrade PyArrow to 23 ### What changes were proposed in this pull request? Upgrade PyArrow to 23 ### Why are the changes needed? refresh the images to test against latest pyarrow ### Does this PR introduce _any_ user-facing change? no, infra-only ### How was this patch tested? 1, for changes in lint/doc/python3-12, the PR builder should cover; 2, for other places, will monitor the scheduled jobs ### Was this patch authored or co-authored using generative AI tooling? no Closes #54504 from zhengruifeng/upgrade_pa_23. Authored-by: Ruifeng Zheng Signed-off-by: Dongjoon Hyun --- .github/workflows/python_hosted_runner_test.yml | 2 +- dev/spark-test-image/docs/Dockerfile | 2 +- dev/spark-test-image/lint/Dockerfile | 2 +- dev/spark-test-image/python-310/Dockerfile | 2 +- dev/spark-test-image/python-311/Dockerfile | 2 +- dev/spark-test-image/python-312-classic-only/Dockerfile | 2 +- dev/spark-test-image/python-312-pandas-3/Dockerfile | 2 +- dev/spark-test-image/python-312/Dockerfile | 2 +- dev/spark-test-image/python-313/Dockerfile | 2 +- dev/spark-test-image/python-314-nogil/Dockerfile | 2 +- dev/spark-test-image/python-314/Dockerfile | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/python_hosted_runner_test.yml b/.github/workflows/python_hosted_runner_test.yml index 235d8e0064ca2..a5aff7ac5ce0d 100644 --- a/.github/workflows/python_hosted_runner_test.yml +++ b/.github/workflows/python_hosted_runner_test.yml @@ -154,7 +154,7 @@ jobs: run: | python${{matrix.python}} -m pip install --ignore-installed 'blinker>=1.6.2' python${{matrix.python}} -m pip install --ignore-installed 'six==1.16.0' - python${{matrix.python}} -m pip install numpy 'pyarrow>=22.0.0' 'six==1.16.0' 'pandas==2.3.3' scipy 'plotly<6.0.0' 'mlflow>=2.8.1' coverage matplotlib openpyxl 'memory-profiler>=0.61.0' 'scikit-learn>=1.3.2' unittest-xml-reporting && \ + python${{matrix.python}} -m pip install numpy 'pyarrow>=23.0.0' 'six==1.16.0' 'pandas==2.3.3' scipy 'plotly<6.0.0' 'mlflow>=2.8.1' coverage matplotlib openpyxl 'memory-profiler>=0.61.0' 'scikit-learn>=1.3.2' unittest-xml-reporting && \ python${{matrix.python}} -m pip install 'grpcio==1.76.0' 'grpcio-status==1.76.0' 'protobuf==6.33.5' 'googleapis-common-protos==1.71.0' 'zstandard==0.25.0' 'graphviz==0.20.3' && \ python${{matrix.python}} -m pip cache purge - name: List Python packages diff --git a/dev/spark-test-image/docs/Dockerfile b/dev/spark-test-image/docs/Dockerfile index 347192b3c334e..1cdfde2d046ce 100644 --- a/dev/spark-test-image/docs/Dockerfile +++ b/dev/spark-test-image/docs/Dockerfile @@ -88,7 +88,7 @@ ENV PATH="$VIRTUAL_ENV/bin:$PATH" # See 'ipython_genutils' in SPARK-38517 # See 'docutils<0.18.0' in SPARK-39421 RUN python3.12 -m pip install 'sphinx==4.5.0' mkdocs 'pydata_sphinx_theme>=0.13' sphinx-copybutton nbsphinx numpydoc jinja2 markupsafe \ - ipython ipython_genutils sphinx_plotly_directive 'numpy>=1.22' pyarrow 'pandas==2.3.3' 'plotly>=4.8' 'docutils<0.18.0' \ + ipython ipython_genutils sphinx_plotly_directive 'numpy>=1.22' 'pyarrow>=23.0.0' 'pandas==2.3.3' 'plotly>=4.8' 'docutils<0.18.0' \ 'flake8==3.9.0' 'mypy==1.19.1' 'pytest==7.1.3' 'pytest-mypy-plugins==1.9.3' 'black==23.12.1' \ 'pandas-stubs==1.2.0.53' 'grpcio==1.76.0' 'grpcio-status==1.76.0' 'protobuf==6.33.5' 'grpc-stubs==1.24.11' 'googleapis-common-protos-stubs==2.2.0' \ 'sphinxcontrib-applehelp==1.0.4' 'sphinxcontrib-devhelp==1.0.2' 'sphinxcontrib-htmlhelp==2.0.1' 'sphinxcontrib-qthelp==1.0.3' 'sphinxcontrib-serializinghtml==1.1.5' \ diff --git a/dev/spark-test-image/lint/Dockerfile b/dev/spark-test-image/lint/Dockerfile index 6fa318ab5d031..ac95c002f4914 100644 --- a/dev/spark-test-image/lint/Dockerfile +++ b/dev/spark-test-image/lint/Dockerfile @@ -95,7 +95,7 @@ RUN python3.12 -m pip install \ 'pandas' \ 'pandas-stubs' \ 'plotly>=4.8' \ - 'pyarrow>=22.0.0' \ + 'pyarrow>=23.0.0' \ 'pytest-mypy-plugins==1.9.3' \ 'pytest==7.1.3' \ 'scipy>=1.8.0' \ diff --git a/dev/spark-test-image/python-310/Dockerfile b/dev/spark-test-image/python-310/Dockerfile index cd1aa79dac5fa..c8752c8bb340a 100644 --- a/dev/spark-test-image/python-310/Dockerfile +++ b/dev/spark-test-image/python-310/Dockerfile @@ -63,7 +63,7 @@ ENV VIRTUAL_ENV=/opt/spark-venv RUN python3.10 -m venv $VIRTUAL_ENV ENV PATH="$VIRTUAL_ENV/bin:$PATH" -ARG BASIC_PIP_PKGS="numpy pyarrow>=22.0.0 six==1.16.0 pandas==2.3.3 scipy plotly<6.0.0 mlflow>=2.8.1 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2 pystack>=1.6.0 psutil" +ARG BASIC_PIP_PKGS="numpy pyarrow>=23.0.0 six==1.16.0 pandas==2.3.3 scipy plotly<6.0.0 mlflow>=2.8.1 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2 pystack>=1.6.0 psutil" ARG CONNECT_PIP_PKGS="grpcio==1.76.0 grpcio-status==1.76.0 protobuf==6.33.5 googleapis-common-protos==1.71.0 zstandard==0.25.0 graphviz==0.20.3" RUN python3.10 -m pip install $BASIC_PIP_PKGS unittest-xml-reporting $CONNECT_PIP_PKGS && \ diff --git a/dev/spark-test-image/python-311/Dockerfile b/dev/spark-test-image/python-311/Dockerfile index 47354e2866f07..9c65caff2efa6 100644 --- a/dev/spark-test-image/python-311/Dockerfile +++ b/dev/spark-test-image/python-311/Dockerfile @@ -60,7 +60,7 @@ ENV VIRTUAL_ENV=/opt/spark-venv RUN python3.11 -m venv $VIRTUAL_ENV ENV PATH="$VIRTUAL_ENV/bin:$PATH" -ARG BASIC_PIP_PKGS="numpy pyarrow>=22.0.0 six==1.16.0 pandas==2.3.3 scipy plotly<6.0.0 mlflow>=2.8.1 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2 pystack>=1.6.0 psutil" +ARG BASIC_PIP_PKGS="numpy pyarrow>=23.0.0 six==1.16.0 pandas==2.3.3 scipy plotly<6.0.0 mlflow>=2.8.1 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2 pystack>=1.6.0 psutil" ARG CONNECT_PIP_PKGS="grpcio==1.76.0 grpcio-status==1.76.0 protobuf==6.33.5 googleapis-common-protos==1.71.0 zstandard==0.25.0 graphviz==0.20.3" RUN python3.11 -m pip install $BASIC_PIP_PKGS unittest-xml-reporting $CONNECT_PIP_PKGS && \ diff --git a/dev/spark-test-image/python-312-classic-only/Dockerfile b/dev/spark-test-image/python-312-classic-only/Dockerfile index 0a2b7b291a444..ba7d34625cc81 100644 --- a/dev/spark-test-image/python-312-classic-only/Dockerfile +++ b/dev/spark-test-image/python-312-classic-only/Dockerfile @@ -56,7 +56,7 @@ ENV VIRTUAL_ENV=/opt/spark-venv RUN python3.12 -m venv $VIRTUAL_ENV ENV PATH="$VIRTUAL_ENV/bin:$PATH" -ARG BASIC_PIP_PKGS="numpy pyarrow>=22.0.0 pandas==2.3.3 plotly<6.0.0 matplotlib openpyxl memory-profiler>=0.61.0 mlflow>=2.8.1 scipy scikit-learn>=1.3.2 pystack>=1.6.0 psutil" +ARG BASIC_PIP_PKGS="numpy pyarrow>=23.0.0 pandas==2.3.3 plotly<6.0.0 matplotlib openpyxl memory-profiler>=0.61.0 mlflow>=2.8.1 scipy scikit-learn>=1.3.2 pystack>=1.6.0 psutil" ARG TEST_PIP_PKGS="coverage unittest-xml-reporting" RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.12 diff --git a/dev/spark-test-image/python-312-pandas-3/Dockerfile b/dev/spark-test-image/python-312-pandas-3/Dockerfile index 101a5884a5a26..6b9844372b468 100644 --- a/dev/spark-test-image/python-312-pandas-3/Dockerfile +++ b/dev/spark-test-image/python-312-pandas-3/Dockerfile @@ -59,7 +59,7 @@ ENV VIRTUAL_ENV=/opt/spark-venv RUN python3.12 -m venv $VIRTUAL_ENV ENV PATH="$VIRTUAL_ENV/bin:$PATH" -ARG BASIC_PIP_PKGS="numpy pyarrow>=22.0.0 six==1.16.0 pandas>=3 scipy plotly<6.0.0 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2" +ARG BASIC_PIP_PKGS="numpy pyarrow>=23.0.0 six==1.16.0 pandas>=3 scipy plotly<6.0.0 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2" ARG CONNECT_PIP_PKGS="grpcio==1.76.0 grpcio-status==1.76.0 protobuf==6.33.5 googleapis-common-protos==1.71.0 zstandard==0.25.0 graphviz==0.20.3" RUN python3.12 -m pip install $BASIC_PIP_PKGS unittest-xml-reporting $CONNECT_PIP_PKGS lxml && \ diff --git a/dev/spark-test-image/python-312/Dockerfile b/dev/spark-test-image/python-312/Dockerfile index 14cdf08621fbe..ad030f4cd5fb8 100644 --- a/dev/spark-test-image/python-312/Dockerfile +++ b/dev/spark-test-image/python-312/Dockerfile @@ -56,7 +56,7 @@ ENV VIRTUAL_ENV=/opt/spark-venv RUN python3.12 -m venv $VIRTUAL_ENV ENV PATH="$VIRTUAL_ENV/bin:$PATH" -ARG BASIC_PIP_PKGS="numpy pyarrow>=22.0.0 six==1.16.0 pandas==2.3.3 scipy plotly<6.0.0 mlflow>=2.8.1 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2 pystack>=1.6.0 psutil" +ARG BASIC_PIP_PKGS="numpy pyarrow>=23.0.0 six==1.16.0 pandas==2.3.3 scipy plotly<6.0.0 mlflow>=2.8.1 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2 pystack>=1.6.0 psutil" ARG CONNECT_PIP_PKGS="grpcio==1.76.0 grpcio-status==1.76.0 protobuf==6.33.5 googleapis-common-protos==1.71.0 zstandard==0.25.0 graphviz==0.20.3" RUN python3.12 -m pip install $BASIC_PIP_PKGS unittest-xml-reporting $CONNECT_PIP_PKGS lxml && \ diff --git a/dev/spark-test-image/python-313/Dockerfile b/dev/spark-test-image/python-313/Dockerfile index dc051d953a1b8..5d4dc161bc1b3 100644 --- a/dev/spark-test-image/python-313/Dockerfile +++ b/dev/spark-test-image/python-313/Dockerfile @@ -60,7 +60,7 @@ ENV VIRTUAL_ENV=/opt/spark-venv RUN python3.13 -m venv $VIRTUAL_ENV ENV PATH="$VIRTUAL_ENV/bin:$PATH" -ARG BASIC_PIP_PKGS="numpy pyarrow>=22.0.0 six==1.16.0 pandas==2.3.3 scipy plotly<6.0.0 mlflow>=2.8.1 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2 pystack>=1.6.0 psutil" +ARG BASIC_PIP_PKGS="numpy pyarrow>=23.0.0 six==1.16.0 pandas==2.3.3 scipy plotly<6.0.0 mlflow>=2.8.1 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2 pystack>=1.6.0 psutil" ARG CONNECT_PIP_PKGS="grpcio==1.76.0 grpcio-status==1.76.0 protobuf==6.33.5 googleapis-common-protos==1.71.0 zstandard==0.25.0 graphviz==0.20.3" RUN python3.13 -m pip install $BASIC_PIP_PKGS unittest-xml-reporting $CONNECT_PIP_PKGS lxml && \ diff --git a/dev/spark-test-image/python-314-nogil/Dockerfile b/dev/spark-test-image/python-314-nogil/Dockerfile index c2687ae1c7ef5..3cc92f9e63f0f 100644 --- a/dev/spark-test-image/python-314-nogil/Dockerfile +++ b/dev/spark-test-image/python-314-nogil/Dockerfile @@ -62,5 +62,5 @@ ENV PATH="$VIRTUAL_ENV/bin:$PATH" # TODO: Add BASIC_PIP_PKGS and CONNECT_PIP_PKGS when it supports Python 3.14 free threaded # TODO: Add lxml, grpcio, grpcio-status back when they support Python 3.14 free threaded -RUN python3.14t -m pip install 'numpy>=2.1' 'pyarrow>=19.0.0' 'six==1.16.0' 'pandas==2.3.3' 'pystack>=1.6.0' scipy coverage matplotlib openpyxl jinja2 psutil && \ +RUN python3.14t -m pip install 'numpy>=2.1' 'pyarrow>=23.0.0' 'six==1.16.0' 'pandas==2.3.3' 'pystack>=1.6.0' scipy coverage matplotlib openpyxl jinja2 psutil && \ python3.14t -m pip cache purge diff --git a/dev/spark-test-image/python-314/Dockerfile b/dev/spark-test-image/python-314/Dockerfile index eb245ec424388..57154301fbacf 100644 --- a/dev/spark-test-image/python-314/Dockerfile +++ b/dev/spark-test-image/python-314/Dockerfile @@ -60,7 +60,7 @@ ENV VIRTUAL_ENV=/opt/spark-venv RUN python3.14 -m venv $VIRTUAL_ENV ENV PATH="$VIRTUAL_ENV/bin:$PATH" -ARG BASIC_PIP_PKGS="numpy pyarrow>=22.0.0 six==1.16.0 pandas==2.3.3 scipy plotly<6.0.0 mlflow>=2.8.1 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2 pystack>=1.6.0 psutil" +ARG BASIC_PIP_PKGS="numpy pyarrow>=23.0.0 six==1.16.0 pandas==2.3.3 scipy plotly<6.0.0 mlflow>=2.8.1 coverage matplotlib openpyxl memory-profiler>=0.61.0 scikit-learn>=1.3.2 pystack>=1.6.0 psutil" ARG CONNECT_PIP_PKGS="grpcio==1.76.0 grpcio-status==1.76.0 protobuf==6.33.5 googleapis-common-protos==1.71.0 zstandard==0.25.0 graphviz==0.20.3" RUN python3.14 -m pip install $BASIC_PIP_PKGS unittest-xml-reporting $CONNECT_PIP_PKGS lxml && \ From f88addf04a34b166d85646bb669963962c47dd60 Mon Sep 17 00:00:00 2001 From: Devin Petersohn Date: Thu, 26 Feb 2026 11:54:30 -0800 Subject: [PATCH 062/130] [SPARK-55662][PS] Implementation of idxmin Axis argument ### What changes were proposed in this pull request? Add axis=1 support for DataFrame.idxmin, matching the existing idxmax axis=1 implementation. ### Why are the changes needed? Implements missing API parameter ### Does this PR introduce _any_ user-facing change? Yes, new parameter ### How was this patch tested? CI ### Was this patch authored or co-authored using generative AI tooling? Co-authored-by: Claude Opus 4 Closes #54455 from devin-petersohn/devin/idxmin_axis_v2. Authored-by: Devin Petersohn Signed-off-by: Takuya Ueshin --- python/pyspark/pandas/frame.py | 80 +++++++++++-- .../tests/computation/test_idxmax_idxmin.py | 112 ++++++++++++++++++ 2 files changed, 181 insertions(+), 11 deletions(-) diff --git a/python/pyspark/pandas/frame.py b/python/pyspark/pandas/frame.py index a9ffcbc9d59d0..4e85c6b73301b 100644 --- a/python/pyspark/pandas/frame.py +++ b/python/pyspark/pandas/frame.py @@ -12450,7 +12450,6 @@ def idxmax(self, axis: Axis = 0) -> "Series": return first_series(DataFrame(internal)) - # TODO(SPARK-46168): axis = 1 def idxmin(self, axis: Axis = 0) -> "Series": """ Return index of first occurrence of minimum over requested axis. @@ -12461,8 +12460,8 @@ def idxmin(self, axis: Axis = 0) -> "Series": Parameters ---------- - axis : 0 or 'index' - Can only be set to 0 now. + axis : {0 or 'index', 1 or 'columns'}, default 0 + The axis to use. 0 or 'index' for row-wise, 1 or 'columns' for column-wise. Returns ------- @@ -12490,6 +12489,15 @@ def idxmin(self, axis: Axis = 0) -> "Series": c 1 dtype: int64 + For axis=1, return the column label of the minimum value in each row: + + >>> psdf.idxmin(axis=1) + 0 a + 1 a + 2 a + 3 b + dtype: object + For Multi-column Index >>> psdf = ps.DataFrame({'a': [1, 2, 3, 2], @@ -12510,17 +12518,67 @@ def idxmin(self, axis: Axis = 0) -> "Series": c z 1 dtype: int64 """ - min_cols = map(lambda scol: F.min(scol), self._internal.data_spark_columns) - sdf_min = self._internal.spark_frame.select(*min_cols).head() + axis = validate_axis(axis) + if axis == 0: + min_cols = map(lambda scol: F.min(scol), self._internal.data_spark_columns) + sdf_min = self._internal.spark_frame.select(*min_cols).head() - conds = ( - scol == min_val for scol, min_val in zip(self._internal.data_spark_columns, sdf_min) - ) - cond = reduce(lambda x, y: x | y, conds) + conds = ( + scol == min_val for scol, min_val in zip(self._internal.data_spark_columns, sdf_min) + ) + cond = reduce(lambda x, y: x | y, conds) - psdf: DataFrame = DataFrame(self._internal.with_filter(cond)) + psdf: DataFrame = DataFrame(self._internal.with_filter(cond)) - return cast(ps.Series, ps.from_pandas(psdf._to_internal_pandas().idxmin())) + return cast(ps.Series, ps.from_pandas(psdf._to_internal_pandas().idxmin())) + else: + from pyspark.pandas.series import first_series + + column_labels = self._internal.column_labels + + if len(column_labels) == 0: + # Check if DataFrame has rows - if yes, raise error; if no, return empty Series + # to match pandas behavior + if len(self) > 0: + raise ValueError("attempt to get argmin of an empty sequence") + else: + return ps.Series([], dtype=np.int64) + + if self._internal.column_labels_level > 1: + raise NotImplementedError( + "idxmin with axis=1 does not support MultiIndex columns yet" + ) + + min_value = F.least( + *[ + F.coalesce(self._internal.spark_column_for(label), F.lit(float("inf"))) + for label in column_labels + ], + F.lit(float("inf")), + ) + + result = None + # Iterate over the column labels in reverse order to get the first occurrence of the + # minimum value. + for label in reversed(column_labels): + scol = self._internal.spark_column_for(label) + label_value = label[0] if len(label) == 1 else label + condition = (scol == min_value) & scol.isNotNull() + + result = ( + F.when(condition, F.lit(label_value)) + if result is None + else F.when(condition, F.lit(label_value)).otherwise(result) + ) + + result = F.when(min_value == float("inf"), F.lit(None)).otherwise(result) + + internal = self._internal.with_new_columns( + [result.alias(SPARK_DEFAULT_SERIES_NAME)], + column_labels=[None], + ) + + return first_series(DataFrame(internal)) def info( self, diff --git a/python/pyspark/pandas/tests/computation/test_idxmax_idxmin.py b/python/pyspark/pandas/tests/computation/test_idxmax_idxmin.py index 2de14fccbc430..6c33b4fd3261e 100644 --- a/python/pyspark/pandas/tests/computation/test_idxmax_idxmin.py +++ b/python/pyspark/pandas/tests/computation/test_idxmax_idxmin.py @@ -155,6 +155,118 @@ def test_idxmax_empty_dataframe(self): # Verify both raise the same error message self.assertEqual(str(pdf_context.exception), str(psdf_context.exception)) + def test_idxmin(self): + # Test basic axis=0 (default) + pdf = pd.DataFrame( + { + "a": [1, 2, 3, 2], + "b": [4.0, 2.0, 3.0, 1.0], + "c": [300, 200, 400, 200], + } + ) + psdf = ps.from_pandas(pdf) + + self.assert_eq(psdf.idxmin(), pdf.idxmin()) + self.assert_eq(psdf.idxmin(axis=0), pdf.idxmin(axis=0)) + self.assert_eq(psdf.idxmin(axis="index"), pdf.idxmin(axis="index")) + + # Test axis=1 + self.assert_eq(psdf.idxmin(axis=1), pdf.idxmin(axis=1)) + self.assert_eq(psdf.idxmin(axis="columns"), pdf.idxmin(axis="columns")) + + # Test with NAs + pdf = pd.DataFrame( + { + "a": [1.0, None, 3.0], + "b": [None, 2.0, None], + "c": [3.0, 4.0, None], + } + ) + psdf = ps.from_pandas(pdf) + + self.assert_eq(psdf.idxmin(), pdf.idxmin()) + self.assert_eq(psdf.idxmin(axis=0), pdf.idxmin(axis=0)) + self.assert_eq(psdf.idxmin(axis=1), pdf.idxmin(axis=1)) + + # Test with all-NA row + pdf = pd.DataFrame( + { + "a": [1.0, None], + "b": [2.0, None], + } + ) + psdf = ps.from_pandas(pdf) + + self.assert_eq(psdf.idxmin(axis=1), pdf.idxmin(axis=1)) + + # Test with ties (first occurrence should win) + pdf = pd.DataFrame( + { + "a": [3, 2, 1], + "b": [3, 5, 1], + "c": [1, 5, 1], + } + ) + psdf = ps.from_pandas(pdf) + + self.assert_eq(psdf.idxmin(axis=1), pdf.idxmin(axis=1)) + + # Test with single column + pdf = pd.DataFrame({"a": [1, 2, 3]}) + psdf = ps.from_pandas(pdf) + + self.assert_eq(psdf.idxmin(axis=1), pdf.idxmin(axis=1)) + + # Test with empty DataFrame + pdf = pd.DataFrame({}) + psdf = ps.from_pandas(pdf) + + self.assert_eq(psdf.idxmin(axis=1), pdf.idxmin(axis=1)) + + # Test with different data types + pdf = pd.DataFrame( + { + "int_col": [1, 2, 3], + "float_col": [1.5, 2.5, 0.5], + "negative": [-5, -10, -1], + } + ) + psdf = ps.from_pandas(pdf) + + self.assert_eq(psdf.idxmin(axis=1), pdf.idxmin(axis=1)) + + # Test with custom index + pdf = pd.DataFrame( + { + "a": [1, 2, 3], + "b": [4, 5, 6], + "c": [7, 8, 9], + }, + index=["row1", "row2", "row3"], + ) + psdf = ps.from_pandas(pdf) + + self.assert_eq(psdf.idxmin(axis=1), pdf.idxmin(axis=1)) + + def test_idxmin_multiindex_columns(self): + # Test that MultiIndex columns raise NotImplementedError for axis=1 + pdf = pd.DataFrame( + { + "a": [1, 2, 3], + "b": [4, 5, 6], + "c": [7, 8, 9], + } + ) + pdf.columns = pd.MultiIndex.from_tuples([("x", "a"), ("y", "b"), ("z", "c")]) + psdf = ps.from_pandas(pdf) + + # axis=0 should work fine (it uses pandas internally) + self.assert_eq(psdf.idxmin(axis=0), pdf.idxmin(axis=0)) + + # axis=1 should raise NotImplementedError + with self.assertRaises(NotImplementedError): + psdf.idxmin(axis=1) + class FrameIdxMaxMinTests( FrameIdxMaxMinMixin, From 08a2cb9213dd7701c562af1f465cbf394b32a38e Mon Sep 17 00:00:00 2001 From: Takuya Ueshin Date: Thu, 26 Feb 2026 11:56:35 -0800 Subject: [PATCH 063/130] [SPARK-55296][PS][FOLLOW-UP] Fix setitem with Series through iloc indexer with pandas 3 ### What changes were proposed in this pull request? This is another follow-up of apache/spark#54375. Fixes `setitem` with `Series` through `iloc` indexer with pandas 3. Also fixed some tests with `DataFrame` with `loc` indexer. ### Why are the changes needed? Setting `Series` through `iloc` indexer causes an analysis exception: ```py >>> from pyspark import pandas as ps >>> psdf = ps.DataFrame({"a": [1, 2, 3], "b": [10, 20, 30]}) >>> psser = psdf["a"] >>> >>> psser.iloc[[0, 1, 2]] = -ps.DataFrame({"x": [100, 200, 300]})["x"] Traceback (most recent call last): ... pyspark.errors.exceptions.captured.AnalysisException: [UNRESOLVED_COLUMN.WITH_SUGGESTION] A column, variable, or function parameter with name `__temp_value_col__` cannot be resolved. Did you mean one of the following? [`__natural_order__`, `__index_level_0__`, `a`, `__distributed_sequence_column__`]. SQLSTATE: 42703; ... ``` ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Updated the related tests and the existing tests should pass. ### Was this patch authored or co-authored using generative AI tooling? Codex (GPT-5.3-Codex) Closes #54498 from ueshin/issues/SPARK-55296/setitem. Authored-by: Takuya Ueshin Signed-off-by: Takuya Ueshin --- python/pyspark/pandas/indexing.py | 17 ++++++++-------- .../diff_frames_ops/test_setitem_frame.py | 20 +++++++++++++------ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/python/pyspark/pandas/indexing.py b/python/pyspark/pandas/indexing.py index 7f26f4ce75956..03d8054c7e2a5 100644 --- a/python/pyspark/pandas/indexing.py +++ b/python/pyspark/pandas/indexing.py @@ -621,17 +621,18 @@ def __setitem__(self, key: Any, value: Any) -> None: psdf[temp_value_col] = value psdf = psdf.sort_values(temp_natural_order).drop(columns=temp_natural_order) - psser = psdf._psser_for(column_label) if isinstance(key, Series): - key = F.col( - "`{}`".format(psdf[temp_key_col]._internal.data_spark_column_names[0]) - ) + key = psdf[temp_key_col].spark.column if isinstance(value, Series): - value = F.col( - "`{}`".format(psdf[temp_value_col]._internal.data_spark_column_names[0]) - ) + value = psdf[temp_value_col].spark.column + + if isinstance(self, iLocIndexer): + col_sel = psdf._internal.column_labels.index(column_label) + else: + col_sel = column_label + type(self)(psdf)[key, col_sel] = value - type(self)(psser)[key] = value + psser = psdf._psser_for(column_label) if self._psdf_or_psser.name is None: psser = psser.rename() diff --git a/python/pyspark/pandas/tests/diff_frames_ops/test_setitem_frame.py b/python/pyspark/pandas/tests/diff_frames_ops/test_setitem_frame.py index 09428da14ee39..45eb8a3705f27 100644 --- a/python/pyspark/pandas/tests/diff_frames_ops/test_setitem_frame.py +++ b/python/pyspark/pandas/tests/diff_frames_ops/test_setitem_frame.py @@ -19,6 +19,7 @@ from pyspark import pandas as ps from pyspark.pandas.config import set_option, reset_option +from pyspark.loose_version import LooseVersion from pyspark.testing.pandasutils import PandasOnSparkTestCase from pyspark.testing.sqlutils import SQLTestUtils @@ -51,8 +52,15 @@ def test_frame_loc_setitem(self): another_psdf = ps.DataFrame(pdf_orig) - psdf.loc[["viper", "sidewinder"], ["shield"]] = -another_psdf.max_speed - pdf.loc[["viper", "sidewinder"], ["shield"]] = -pdf.max_speed + if LooseVersion(pd.__version__) < "3.0.0": + shield_sel = ["shield"] + else: + # pandas 3 CoW can raise a shape-mismatch error for `loc[..., ["shield"]] = Series` + # when Series views are already referenced. Use scalar column selection instead. + shield_sel = "shield" + + psdf.loc[["viper", "sidewinder"], shield_sel] = -another_psdf.max_speed + pdf.loc[["viper", "sidewinder"], shield_sel] = -pdf.max_speed self.assert_eq(psdf, pdf) self.assert_eq(psser1, pser1) self.assert_eq(psser2, pser2) @@ -63,8 +71,8 @@ def test_frame_loc_setitem(self): pser2 = pdf.shield psser1 = psdf.max_speed psser2 = psdf.shield - psdf.loc[another_psdf.max_speed < 5, ["shield"]] = -psdf.max_speed - pdf.loc[pdf.max_speed < 5, ["shield"]] = -pdf.max_speed + psdf.loc[another_psdf.max_speed < 5, shield_sel] = -psdf.max_speed + pdf.loc[pdf.max_speed < 5, shield_sel] = -pdf.max_speed self.assert_eq(psdf, pdf) self.assert_eq(psser1, pser1) self.assert_eq(psser2, pser2) @@ -75,8 +83,8 @@ def test_frame_loc_setitem(self): pser2 = pdf.shield psser1 = psdf.max_speed psser2 = psdf.shield - psdf.loc[another_psdf.max_speed < 5, ["shield"]] = -another_psdf.max_speed - pdf.loc[pdf.max_speed < 5, ["shield"]] = -pdf.max_speed + psdf.loc[another_psdf.max_speed < 5, shield_sel] = -another_psdf.max_speed + pdf.loc[pdf.max_speed < 5, shield_sel] = -pdf.max_speed self.assert_eq(psdf, pdf) self.assert_eq(psser1, pser1) self.assert_eq(psser2, pser2) From 9e6b2571868812cc960f79ac5ced6eda6b89266f Mon Sep 17 00:00:00 2001 From: Takuya Ueshin Date: Thu, 26 Feb 2026 11:57:25 -0800 Subject: [PATCH 064/130] [SPARK-55700][PS] Fix handling integer keys on Series with non-integer index ### What changes were proposed in this pull request? Fixes handling integer keys on Series with non-integer index. ### Why are the changes needed? Integer keys on Series with non-integer index doesn't handle them as positional index with pandas 3 anymore. For example: ```py >>> dates = pd.date_range("20130101", periods=6) >>> pdf = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list("ABCD")) ``` - pandas 2 ```py >>> pdf.A[4] :1: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]` np.float64(-1.2836101861392761) ``` - pandas 3 ```py >>> pdf.A[4] Traceback (most recent call last): ... KeyError: 4 ``` ### Does this PR introduce _any_ user-facing change? Yes, it will behave more like pandas 3. ### How was this patch tested? Updated the related tests. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54499 from ueshin/issues/SPARK-55700/treating_keys_as_positions. Authored-by: Takuya Ueshin Signed-off-by: Takuya Ueshin --- python/pyspark/pandas/series.py | 27 +++++++++++-------- .../pandas/tests/indexes/test_indexing_adv.py | 9 +++++-- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/python/pyspark/pandas/series.py b/python/pyspark/pandas/series.py index 1015ff4db4d94..f1fb0069fa74b 100644 --- a/python/pyspark/pandas/series.py +++ b/python/pyspark/pandas/series.py @@ -7354,19 +7354,24 @@ def resample( ) def __getitem__(self, key: Any) -> Any: - if type(key) == int and not isinstance(self.index.spark.data_type, (IntegerType, LongType)): - warnings.warn( - "Series.__getitem__ treating keys as positions is deprecated. " - "In a future version, integer keys will always be treated as labels " - "(consistent with DataFrame behavior). " - "To access a value by position, use `ser.iloc[pos]`", - FutureWarning, + if LooseVersion(pd.__version__) < "3.0.0": + treating_keys_as_positions = type(key) == int and not isinstance( + self.index.spark.data_type, (IntegerType, LongType) ) + if treating_keys_as_positions: + warnings.warn( + "Series.__getitem__ treating keys as positions is deprecated. " + "In a future version, integer keys will always be treated as labels " + "(consistent with DataFrame behavior). " + "To access a value by position, use `ser.iloc[pos]`", + FutureWarning, + ) + else: + treating_keys_as_positions = False try: - if (isinstance(key, slice) and any(type(n) == int for n in [key.start, key.stop])) or ( - type(key) == int - and not isinstance(self.index.spark.data_type, (IntegerType, LongType)) - ): + if ( + isinstance(key, slice) and any(type(n) == int for n in [key.start, key.stop]) + ) or treating_keys_as_positions: # Seems like pandas Series always uses int as positional search when slicing # with ints, searches based on index values when the value is int. return self.iloc[key] diff --git a/python/pyspark/pandas/tests/indexes/test_indexing_adv.py b/python/pyspark/pandas/tests/indexes/test_indexing_adv.py index fdebdcbd00026..90c9d5dbb0ef1 100644 --- a/python/pyspark/pandas/tests/indexes/test_indexing_adv.py +++ b/python/pyspark/pandas/tests/indexes/test_indexing_adv.py @@ -22,6 +22,7 @@ import pandas as pd from pyspark import pandas as ps +from pyspark.loose_version import LooseVersion from pyspark.pandas.exceptions import SparkPandasNotImplementedError from pyspark.testing.pandasutils import PandasOnSparkTestCase from pyspark.testing.sqlutils import SQLTestUtils @@ -339,8 +340,12 @@ def test_index_operator_datetime(self): self.assert_eq(psdf[10:3], pdf[10:3], almost=True) # Index loc search - self.assert_eq(psdf.A[4], pdf.A[4]) - self.assert_eq(psdf.A[3], pdf.A[3]) + if LooseVersion(pd.__version__) < "3.0.0": + self.assert_eq(psdf.A[4], pdf.A[4]) + self.assert_eq(psdf.A[3], pdf.A[3]) + else: + with self.assertRaises(KeyError): + psdf.A[4] # Positional iloc search self.assert_eq(psdf.A[:4], pdf.A[:4], almost=True) From 4da26e4bf9eab119ff2489c5fdf85efe60f6f469 Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Thu, 26 Feb 2026 14:11:12 -0800 Subject: [PATCH 065/130] [SPARK-55683][SQL][FOLLOWUP] Optimize `VectorizedPlainValuesReader.readUnsignedLongs` to reuse scratch buffer and avoid per-element allocations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? This pr refer to the suggestion from Copilot: https://github.com/apache/spark/pull/54479#pullrequestreview-3855142296, further optimizes `VectorizedPlainValuesReader.readUnsignedLongs` by introducing a reusable scratch buffer to eliminate per-element `byte[]` allocations introduced in the previous refactoring. The previous implementation allocates a new `byte[]` per element for the encoded output: ```java // Previous: new byte[totalLen] per element, plus new byte[]{0} for zero values byte[] dest = new byte[totalLen]; ... c.putByteArray(rowId, dest, 0, totalLen); ``` The new implementation allocates a single `byte[9]` scratch buffer once per batch and reuses it across all elements. Since `WritableColumnVector.putByteArray` copies the bytes into its internal storage immediately, the scratch buffer can be safely overwritten on the next iteration: ```java // New: one byte[9] allocated per batch, reused for every element byte[] scratch = new byte[9]; for (...) { putLittleEndianBytesAsBigInteger(c, rowId, src, offset, scratch); } ``` The scratch buffer is sized at 9 bytes to accommodate the worst case: 1 `0x00` sign byte + 8 value bytes. The zero value special case is also handled via scratch, avoiding the previous `new byte[]{0}` allocation. ### Why are the changes needed? The previous implementation still allocates one `byte[]` per element for the encoded output. For a typical batch of 4096 values this means 4096 heap allocations per `readUnsignedLongs` call, creating GC pressure in workloads that read large `UINT_64` columns. With the scratch buffer approach, the entire batch produces only 2 allocations: `byte[9]` (scratch) and `byte[8]` (direct buffer fallback read buffer), regardless of batch size. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? - Pass Github Action - Reused the JMH benchmark provided in https://github.com/apache/spark/pull/54479, and the test results are as follows: Java 17 ``` [info] Benchmark (numValues) Mode Cnt Score Error Units [info] VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_offHeap_New 10000000 avgt 10 233820.658 ± 1888.523 us/op [info] VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_offHeap_Old 10000000 avgt 10 255563.248 ± 3500.165 us/op [info] VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_onHeap_New 10000000 avgt 10 228672.684 ± 2985.496 us/op [info] VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_onHeap_Old 10000000 avgt 10 275756.804 ± 2065.405 us/op ``` Java 21 ``` [info] Benchmark (numValues) Mode Cnt Score Error Units [info] VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_offHeap_New 10000000 avgt 10 241977.924 ± 15125.343 us/op [info] VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_offHeap_Old 10000000 avgt 10 250343.470 ± 1342.509 us/op [info] VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_onHeap_New 10000000 avgt 10 212929.948 ± 1387.671 us/op [info] VectorizedPlainValuesReaderJMHBenchmark.readUnsignedLongs_onHeap_Old 10000000 avgt 10 274561.949 ± 1226.348 us/op ``` Judging from the test results, the onHeap path demonstrates approximately a 17-22% improvement, while the offHeap path shows roughly a 3-9% improvement across Java 17 and Java 21. ### Was this patch authored or co-authored using generative AI tooling? Yes, Claude Sonnet 4.6 was used to assist in completing the code writing. Closes #54510 from LuciferYang/SPARK-55683-FOLLOWUP. Lead-authored-by: yangjie01 Co-authored-by: YangJie Signed-off-by: Dongjoon Hyun --- .../parquet/VectorizedPlainValuesReader.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java index 9ad07a1ff5eeb..852d02c2cdf1c 100644 --- a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java +++ b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedPlainValuesReader.java @@ -198,18 +198,20 @@ public void skipLongs(int total) { public final void readUnsignedLongs(int total, WritableColumnVector c, int rowId) { int requiredBytes = total * 8; ByteBuffer buffer = getBuffer(requiredBytes); + // scratch buffer: max 9 bytes (0x00 sign byte + 8 value bytes), reused per batch + byte[] scratch = new byte[9]; if (buffer.hasArray()) { byte[] src = buffer.array(); int offset = buffer.arrayOffset() + buffer.position(); for (int i = 0; i < total; i++, rowId++, offset += 8) { - putLittleEndianBytesAsBigInteger(c, rowId, src, offset); + putLittleEndianBytesAsBigInteger(c, rowId, src, offset, scratch); } } else { // direct buffer fallback: copy 8 bytes per value byte[] data = new byte[8]; for (int i = 0; i < total; i++, rowId++) { buffer.get(data); - putLittleEndianBytesAsBigInteger(c, rowId, data, 0); + putLittleEndianBytesAsBigInteger(c, rowId, data, 0, scratch); } } } @@ -239,9 +241,11 @@ public final void readUnsignedLongs(int total, WritableColumnVector c, int rowId * @param src the source byte array containing little-endian encoded data * @param offset the starting position in {@code src}; reads bytes * {@code src[offset..offset+7]} + * @param scratch a caller-provided reusable buffer of at least 9 bytes; its contents + * after this call are undefined */ private static void putLittleEndianBytesAsBigInteger( - WritableColumnVector c, int rowId, byte[] src, int offset) { + WritableColumnVector c, int rowId, byte[] src, int offset, byte[] scratch) { // src is little-endian; the most significant byte is at src[offset + 7]. // Scan from the most significant end to find the first non-zero byte, // which determines the minimal number of bytes needed for encoding. @@ -254,7 +258,9 @@ private static void putLittleEndianBytesAsBigInteger( // BigInteger.ZERO.toByteArray() returns [0x00], and new BigInteger(new byte[0]) // throws NumberFormatException("Zero length BigInteger"). if (msbIndex == offset && src[offset] == 0) { - c.putByteArray(rowId, new byte[]{0}); + scratch[0] = 0x00; + // putByteArray copies the bytes into arrayData(), so scratch can be safely reused + c.putByteArray(rowId, scratch, 0, 1); return; } @@ -266,16 +272,16 @@ private static void putLittleEndianBytesAsBigInteger( int valueLen = msbIndex - offset + 1; int totalLen = needSignByte ? valueLen + 1 : valueLen; - byte[] dest = new byte[totalLen]; - int destOffset = 0; + int scratchOffset = 0; if (needSignByte) { - dest[destOffset++] = 0x00; + scratch[scratchOffset++] = 0x00; } // Reverse byte order: little-endian src → big-endian dest for (int i = msbIndex; i >= offset; i--) { - dest[destOffset++] = src[i]; + scratch[scratchOffset++] = src[i]; } - c.putByteArray(rowId, dest, 0, totalLen); + // putByteArray copies the bytes into arrayData(), so scratch can be safely reused + c.putByteArray(rowId, scratch, 0, totalLen); } // A fork of `readLongs` to rebase the timestamp values. For performance reasons, this method From 6775a1729dca25294bca9a33f987891ec58e031f Mon Sep 17 00:00:00 2001 From: Wenchen Fan Date: Fri, 27 Feb 2026 09:01:09 +0800 Subject: [PATCH 066/130] [SPARK-55702][SQL] Support filter predicate in window aggregate functions ### What changes were proposed in this pull request? This PR adds support for the `FILTER (WHERE ...)` clause on aggregate functions used within window expressions. Previously, Spark rejected this with an `AnalysisException` ("Window aggregate function with filter predicate is not supported yet."). The changes are: 1. **Remove the analysis rejection** in `Analyzer.scala` that blocked `FILTER` in window aggregates, and extract filter expressions alongside aggregate function children. 2. **Add filter support to `AggregateProcessor`** so that `AggregateExpression.filter` is honored during window frame evaluation: - For `DeclarativeAggregate`: update expressions are wrapped with `If(filter, updateExpr, bufferAttr)` to conditionally skip rows. - For `ImperativeAggregate`: the filter predicate is evaluated before calling `update()`. 3. **Pass filter expressions from `WindowEvaluatorFactoryBase`** to `AggregateProcessor`. ### Why are the changes needed? The SQL standard allows `FILTER` on aggregate functions in window contexts. Other databases (PostgreSQL, etc.) support this. Spark already supports `FILTER` for regular (non-window) aggregates but rejected it in window contexts. ### Does this PR introduce _any_ user-facing change? Yes. Window aggregate expressions with `FILTER` now execute instead of throwing an `AnalysisException`. For example: ```sql SELECT val, cate, sum(val) FILTER (WHERE val > 1) OVER (PARTITION BY cate ORDER BY val ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_sum_filtered FROM testData ``` ### How was this patch tested? Added 4 SQL test cases in `window.sql` covering: - Running sum with filter - `first_value`/`last_value` with filter (verifying no interference with NULL handling) - Multiple aggregates with different filters in the same window - Entire partition frame with filter The existing test case (`count(val) FILTER (WHERE val > 1) OVER(...)`) now produces correct results instead of an error. ### Was this patch authored or co-authored using generative AI tooling? Yes. Made with [Cursor](https://cursor.com) Closes #54501 from cloud-fan/window-agg-filter. Authored-by: Wenchen Fan Signed-off-by: Wenchen Fan --- .../sql/catalyst/analysis/Analyzer.scala | 8 +- .../analysis/AnalysisErrorSuite.scala | 13 --- .../execution/window/AggregateProcessor.scala | 37 +++++-- .../window/WindowEvaluatorFactoryBase.scala | 7 +- .../sql-tests/analyzer-results/window.sql.out | 102 +++++++++++++++++- .../resources/sql-tests/inputs/window.sql | 34 +++++- .../sql-tests/results/window.sql.out | 99 +++++++++++++++-- 7 files changed, 261 insertions(+), 39 deletions(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala index 04bad39a88baf..a1ec413933dbd 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala @@ -3256,16 +3256,14 @@ class Analyzer( } wsc.copy(partitionSpec = newPartitionSpec, orderSpec = newOrderSpec) - case WindowExpression(ae: AggregateExpression, _) if ae.filter.isDefined => - throw QueryCompilationErrors.windowAggregateFunctionWithFilterNotSupportedError() - // Extract Windowed AggregateExpression case we @ WindowExpression( - ae @ AggregateExpression(function, _, _, _, _), + ae @ AggregateExpression(function, _, _, filter, _), spec: WindowSpecDefinition) => val newChildren = function.children.map(extractExpr) val newFunction = function.withNewChildren(newChildren).asInstanceOf[AggregateFunction] - val newAgg = ae.copy(aggregateFunction = newFunction) + val newFilter = filter.map(extractExpr) + val newAgg = ae.copy(aggregateFunction = newFunction, filter = newFilter) seenWindowAggregates += newAgg WindowExpression(newAgg, spec) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisErrorSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisErrorSuite.scala index 94f650bc35c77..ee644fc62a1ab 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisErrorSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisErrorSuite.scala @@ -208,19 +208,6 @@ class AnalysisErrorSuite extends AnalysisTest with DataTypeErrorsBase { | RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)" |""".stripMargin.replaceAll("\n", ""))) - errorTest( - "window aggregate function with filter predicate", - testRelation2.select( - WindowExpression( - Count(UnresolvedAttribute("b")) - .toAggregateExpression(isDistinct = false, filter = Some(UnresolvedAttribute("b") > 1)), - WindowSpecDefinition( - UnresolvedAttribute("a") :: Nil, - SortOrder(UnresolvedAttribute("b"), Ascending) :: Nil, - UnspecifiedFrame)).as("window")), - "window aggregate function with filter predicate is not supported" :: Nil - ) - test("distinct function") { assertAnalysisErrorCondition( CatalystSqlParser.parsePlan("SELECT hex(DISTINCT a) FROM TaBlE"), diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/window/AggregateProcessor.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/window/AggregateProcessor.scala index 60ce6b068904e..63934944c21a3 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/window/AggregateProcessor.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/window/AggregateProcessor.scala @@ -46,13 +46,17 @@ private[window] object AggregateProcessor { functions: Array[Expression], ordinal: Int, inputAttributes: Seq[Attribute], - newMutableProjection: (Seq[Expression], Seq[Attribute]) => MutableProjection) + newMutableProjection: (Seq[Expression], Seq[Attribute]) => MutableProjection, + filters: Array[Option[Expression]]) : AggregateProcessor = { + assert(filters.length == functions.length, + s"filters length (${filters.length}) must match functions length (${functions.length})") val aggBufferAttributes = mutable.Buffer.empty[AttributeReference] val initialValues = mutable.Buffer.empty[Expression] val updateExpressions = mutable.Buffer.empty[Expression] val evaluateExpressions = mutable.Buffer.fill[Expression](ordinal)(NoOp) val imperatives = mutable.Buffer.empty[ImperativeAggregate] + val imperativeFilterExprs = mutable.Buffer.empty[Option[Expression]] // SPARK-14244: `SizeBasedWindowFunction`s are firstly created on driver side and then // serialized to executor side. These functions all reference a global singleton window @@ -73,25 +77,34 @@ private[window] object AggregateProcessor { } // Add an AggregateFunction to the AggregateProcessor. - functions.foreach { - case agg: DeclarativeAggregate => + functions.zip(filters).foreach { + case (agg: DeclarativeAggregate, filterOpt) => aggBufferAttributes ++= agg.aggBufferAttributes initialValues ++= agg.initialValues - updateExpressions ++= agg.updateExpressions + filterOpt match { + case Some(filter) => + updateExpressions ++= agg.updateExpressions.zip(agg.aggBufferAttributes).map { + case (updateExpr, attr) => If(filter, updateExpr, attr) + } + case None => + updateExpressions ++= agg.updateExpressions + } evaluateExpressions += agg.evaluateExpression - case agg: ImperativeAggregate => + case (agg: ImperativeAggregate, filterOpt) => val offset = aggBufferAttributes.size val imperative = BindReferences.bindReference(agg .withNewInputAggBufferOffset(offset) .withNewMutableAggBufferOffset(offset), inputAttributes) imperatives += imperative + imperativeFilterExprs += filterOpt.map(f => + BindReferences.bindReference(f, inputAttributes)) aggBufferAttributes ++= imperative.aggBufferAttributes val noOps = Seq.fill(imperative.aggBufferAttributes.size)(NoOp) initialValues ++= noOps updateExpressions ++= noOps evaluateExpressions += imperative - case other => + case (other, _) => throw SparkException.internalError(s"Unsupported aggregate function: $other") } @@ -108,6 +121,7 @@ private[window] object AggregateProcessor { updateProj, evalProj, imperatives.toArray, + imperativeFilterExprs.toArray, partitionSize.isDefined) } } @@ -122,6 +136,7 @@ private[window] final class AggregateProcessor( private[this] val updateProjection: MutableProjection, private[this] val evaluateProjection: MutableProjection, private[this] val imperatives: Array[ImperativeAggregate], + private[this] val imperativeFilters: Array[Option[Expression]], private[this] val trackPartitionSize: Boolean) { private[this] val join = new JoinedRow @@ -152,7 +167,15 @@ private[window] final class AggregateProcessor( updateProjection(join(buffer, input)) var i = 0 while (i < numImperatives) { - imperatives(i).update(buffer, input) + val shouldUpdate = imperativeFilters(i) match { + case Some(filter) => + val result = filter.eval(input) + result != null && result.asInstanceOf[Boolean] + case None => true + } + if (shouldUpdate) { + imperatives(i).update(buffer, input) + } i += 1 } } diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/window/WindowEvaluatorFactoryBase.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/window/WindowEvaluatorFactoryBase.scala index c2dedda832e2e..9930c4a8963ab 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/window/WindowEvaluatorFactoryBase.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/window/WindowEvaluatorFactoryBase.scala @@ -194,12 +194,17 @@ trait WindowEvaluatorFactoryBase { def processor = if (functions.exists(_.isInstanceOf[PythonFuncExpression])) { null } else { + val aggFilters = expressions.map { + case WindowExpression(ae: AggregateExpression, _) => ae.filter + case _ => None + }.toArray AggregateProcessor( functions, ordinal, childOutput, (expressions, schema) => - MutableProjection.create(expressions, schema)) + MutableProjection.create(expressions, schema), + aggFilters) } // Create the factory to produce WindowFunctionFrame. diff --git a/sql/core/src/test/resources/sql-tests/analyzer-results/window.sql.out b/sql/core/src/test/resources/sql-tests/analyzer-results/window.sql.out index a441256d3bf0b..76c0fb1919ce1 100644 --- a/sql/core/src/test/resources/sql-tests/analyzer-results/window.sql.out +++ b/sql/core/src/test/resources/sql-tests/analyzer-results/window.sql.out @@ -688,13 +688,105 @@ Project [cate#x, sum(val) OVER (PARTITION BY cate ORDER BY val ASC NULLS FIRST R -- !query SELECT val, cate, -count(val) FILTER (WHERE val > 1) OVER(PARTITION BY cate) +first_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS first_a, +last_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS last_a +FROM testData ORDER BY val_long, cate +-- !query analysis +Project [val#x, cate#x, first_a#x, last_a#x] ++- Sort [val_long#xL ASC NULLS FIRST, cate#x ASC NULLS FIRST], true + +- Project [val#x, cate#x, first_a#x, last_a#x, val_long#xL] + +- Project [val#x, cate#x, _w0#x, val_long#xL, first_a#x, last_a#x, first_a#x, last_a#x] + +- Window [first_value(val#x, false) FILTER (WHERE _w0#x) windowspecdefinition(val_long#xL ASC NULLS FIRST, specifiedwindowframe(RowFrame, unboundedpreceding$(), currentrow$())) AS first_a#x, last_value(val#x, false) FILTER (WHERE _w0#x) windowspecdefinition(val_long#xL ASC NULLS FIRST, specifiedwindowframe(RowFrame, unboundedpreceding$(), currentrow$())) AS last_a#x], [val_long#xL ASC NULLS FIRST] + +- Project [val#x, cate#x, (cate#x = a) AS _w0#x, val_long#xL] + +- SubqueryAlias testdata + +- View (`testData`, [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x]) + +- Project [cast(val#x as int) AS val#x, cast(val_long#xL as bigint) AS val_long#xL, cast(val_double#x as double) AS val_double#x, cast(val_date#x as date) AS val_date#x, cast(val_timestamp#x as timestamp) AS val_timestamp#x, cast(cate#x as string) AS cate#x] + +- Project [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x] + +- SubqueryAlias testData + +- LocalRelation [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x] + + +-- !query +SELECT val, cate, +sum(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS sum_a, +sum(val) FILTER (WHERE cate = 'b') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS sum_b, +count(val) FILTER (WHERE val > 1) OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cnt_gt1 +FROM testData ORDER BY val_long, cate +-- !query analysis +Project [val#x, cate#x, sum_a#xL, sum_b#xL, cnt_gt1#xL] ++- Sort [val_long#xL ASC NULLS FIRST, cate#x ASC NULLS FIRST], true + +- Project [val#x, cate#x, sum_a#xL, sum_b#xL, cnt_gt1#xL, val_long#xL] + +- Project [val#x, cate#x, _w0#x, val_long#xL, _w2#x, _w3#x, sum_a#xL, sum_b#xL, cnt_gt1#xL, sum_a#xL, sum_b#xL, cnt_gt1#xL] + +- Window [sum(val#x) FILTER (WHERE _w0#x) windowspecdefinition(val_long#xL ASC NULLS FIRST, specifiedwindowframe(RowFrame, unboundedpreceding$(), currentrow$())) AS sum_a#xL, sum(val#x) FILTER (WHERE _w2#x) windowspecdefinition(val_long#xL ASC NULLS FIRST, specifiedwindowframe(RowFrame, unboundedpreceding$(), currentrow$())) AS sum_b#xL, count(val#x) FILTER (WHERE _w3#x) windowspecdefinition(val_long#xL ASC NULLS FIRST, specifiedwindowframe(RowFrame, unboundedpreceding$(), currentrow$())) AS cnt_gt1#xL], [val_long#xL ASC NULLS FIRST] + +- Project [val#x, cate#x, (cate#x = a) AS _w0#x, val_long#xL, (cate#x = b) AS _w2#x, (val#x > 1) AS _w3#x] + +- SubqueryAlias testdata + +- View (`testData`, [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x]) + +- Project [cast(val#x as int) AS val#x, cast(val_long#xL as bigint) AS val_long#xL, cast(val_double#x as double) AS val_double#x, cast(val_date#x as date) AS val_date#x, cast(val_timestamp#x as timestamp) AS val_timestamp#x, cast(cate#x as string) AS cate#x] + +- Project [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x] + +- SubqueryAlias testData + +- LocalRelation [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x] + + +-- !query +SELECT val, cate, +sum(val) FILTER (WHERE cate = 'a') OVER(PARTITION BY cate) AS total_sum_filtered FROM testData ORDER BY cate, val -- !query analysis -org.apache.spark.sql.AnalysisException -{ - "errorClass" : "_LEGACY_ERROR_TEMP_1030" -} +Sort [cate#x ASC NULLS FIRST, val#x ASC NULLS FIRST], true ++- Project [val#x, cate#x, total_sum_filtered#xL] + +- Project [val#x, cate#x, _w0#x, total_sum_filtered#xL, total_sum_filtered#xL] + +- Window [sum(val#x) FILTER (WHERE _w0#x) windowspecdefinition(cate#x, specifiedwindowframe(RowFrame, unboundedpreceding$(), unboundedfollowing$())) AS total_sum_filtered#xL], [cate#x] + +- Project [val#x, cate#x, (cate#x = a) AS _w0#x] + +- SubqueryAlias testdata + +- View (`testData`, [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x]) + +- Project [cast(val#x as int) AS val#x, cast(val_long#xL as bigint) AS val_long#xL, cast(val_double#x as double) AS val_double#x, cast(val_date#x as date) AS val_date#x, cast(val_timestamp#x as timestamp) AS val_timestamp#x, cast(cate#x as string) AS cate#x] + +- Project [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x] + +- SubqueryAlias testData + +- LocalRelation [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x] + + +-- !query +SELECT val, cate, +sum(val) FILTER (WHERE val > 1) OVER(ORDER BY val_long + ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS sliding_sum_filtered +FROM testData ORDER BY val_long, cate +-- !query analysis +Project [val#x, cate#x, sliding_sum_filtered#xL] ++- Sort [val_long#xL ASC NULLS FIRST, cate#x ASC NULLS FIRST], true + +- Project [val#x, cate#x, sliding_sum_filtered#xL, val_long#xL] + +- Project [val#x, cate#x, _w0#x, val_long#xL, sliding_sum_filtered#xL, sliding_sum_filtered#xL] + +- Window [sum(val#x) FILTER (WHERE _w0#x) windowspecdefinition(val_long#xL ASC NULLS FIRST, specifiedwindowframe(RowFrame, -1, 1)) AS sliding_sum_filtered#xL], [val_long#xL ASC NULLS FIRST] + +- Project [val#x, cate#x, (val#x > 1) AS _w0#x, val_long#xL] + +- SubqueryAlias testdata + +- View (`testData`, [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x]) + +- Project [cast(val#x as int) AS val#x, cast(val_long#xL as bigint) AS val_long#xL, cast(val_double#x as double) AS val_double#x, cast(val_date#x as date) AS val_date#x, cast(val_timestamp#x as timestamp) AS val_timestamp#x, cast(cate#x as string) AS cate#x] + +- Project [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x] + +- SubqueryAlias testData + +- LocalRelation [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x] + + +-- !query +SELECT val, cate, +sum(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS range_sum_filtered +FROM testData ORDER BY val, cate +-- !query analysis +Sort [val#x ASC NULLS FIRST, cate#x ASC NULLS FIRST], true ++- Project [val#x, cate#x, range_sum_filtered#xL] + +- Project [val#x, cate#x, _w0#x, range_sum_filtered#xL, range_sum_filtered#xL] + +- Window [sum(val#x) FILTER (WHERE _w0#x) windowspecdefinition(val#x ASC NULLS FIRST, specifiedwindowframe(RangeFrame, unboundedpreceding$(), currentrow$())) AS range_sum_filtered#xL], [val#x ASC NULLS FIRST] + +- Project [val#x, cate#x, (cate#x = a) AS _w0#x] + +- SubqueryAlias testdata + +- View (`testData`, [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x]) + +- Project [cast(val#x as int) AS val#x, cast(val_long#xL as bigint) AS val_long#xL, cast(val_double#x as double) AS val_double#x, cast(val_date#x as date) AS val_date#x, cast(val_timestamp#x as timestamp) AS val_timestamp#x, cast(cate#x as string) AS cate#x] + +- Project [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x] + +- SubqueryAlias testData + +- LocalRelation [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x] -- !query diff --git a/sql/core/src/test/resources/sql-tests/inputs/window.sql b/sql/core/src/test/resources/sql-tests/inputs/window.sql index bec79247f9a61..586fe88ac3051 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/window.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/window.sql @@ -182,11 +182,41 @@ FROM testData WHERE val is not null WINDOW w AS (PARTITION BY cate ORDER BY val); --- with filter predicate +-- window aggregate with filter predicate: first_value/last_value (imperative aggregate) SELECT val, cate, -count(val) FILTER (WHERE val > 1) OVER(PARTITION BY cate) +first_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS first_a, +last_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS last_a +FROM testData ORDER BY val_long, cate; + +-- window aggregate with filter predicate: multiple aggregates with different filters +SELECT val, cate, +sum(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS sum_a, +sum(val) FILTER (WHERE cate = 'b') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS sum_b, +count(val) FILTER (WHERE val > 1) OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cnt_gt1 +FROM testData ORDER BY val_long, cate; + +-- window aggregate with filter predicate: entire partition frame +SELECT val, cate, +sum(val) FILTER (WHERE cate = 'a') OVER(PARTITION BY cate) AS total_sum_filtered FROM testData ORDER BY cate, val; +-- window aggregate with filter predicate: sliding window (ROWS frame) +SELECT val, cate, +sum(val) FILTER (WHERE val > 1) OVER(ORDER BY val_long + ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS sliding_sum_filtered +FROM testData ORDER BY val_long, cate; + +-- window aggregate with filter predicate: RANGE frame +SELECT val, cate, +sum(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS range_sum_filtered +FROM testData ORDER BY val, cate; + -- nth_value()/first_value()/any_value() over () SELECT employee_name, diff --git a/sql/core/src/test/resources/sql-tests/results/window.sql.out b/sql/core/src/test/resources/sql-tests/results/window.sql.out index ce88fb57f8aa6..44c3b175868de 100644 --- a/sql/core/src/test/resources/sql-tests/results/window.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/window.sql.out @@ -669,15 +669,102 @@ b 6 -- !query SELECT val, cate, -count(val) FILTER (WHERE val > 1) OVER(PARTITION BY cate) +first_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS first_a, +last_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS last_a +FROM testData ORDER BY val_long, cate +-- !query schema +struct +-- !query output +NULL NULL 1 NULL +1 b 1 NULL +3 NULL 1 1 +NULL a 1 NULL +1 a 1 1 +1 a 1 1 +2 b 1 1 +2 a 1 2 +3 b 1 2 + + +-- !query +SELECT val, cate, +sum(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS sum_a, +sum(val) FILTER (WHERE cate = 'b') OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS sum_b, +count(val) FILTER (WHERE val > 1) OVER(ORDER BY val_long + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cnt_gt1 +FROM testData ORDER BY val_long, cate +-- !query schema +struct +-- !query output +NULL NULL NULL 1 0 +1 b NULL 1 0 +3 NULL 1 1 1 +NULL a NULL 1 0 +1 a 1 1 0 +1 a 2 1 1 +2 b 2 3 2 +2 a 4 3 3 +3 b 4 6 4 + + +-- !query +SELECT val, cate, +sum(val) FILTER (WHERE cate = 'a') OVER(PARTITION BY cate) AS total_sum_filtered FROM testData ORDER BY cate, val -- !query schema -struct<> +struct -- !query output -org.apache.spark.sql.AnalysisException -{ - "errorClass" : "_LEGACY_ERROR_TEMP_1030" -} +NULL NULL NULL +3 NULL NULL +NULL a 4 +1 a 4 +1 a 4 +2 a 4 +1 b NULL +2 b NULL +3 b NULL + + +-- !query +SELECT val, cate, +sum(val) FILTER (WHERE val > 1) OVER(ORDER BY val_long + ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS sliding_sum_filtered +FROM testData ORDER BY val_long, cate +-- !query schema +struct +-- !query output +NULL NULL NULL +1 b NULL +3 NULL 3 +NULL a NULL +1 a 3 +1 a 5 +2 b 4 +2 a 7 +3 b 5 + + +-- !query +SELECT val, cate, +sum(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS range_sum_filtered +FROM testData ORDER BY val, cate +-- !query schema +struct +-- !query output +NULL NULL NULL +NULL a NULL +1 a 2 +1 a 2 +1 b 2 +2 a 4 +2 b 4 +3 NULL 4 +3 b 4 -- !query From 3b343b4d5c5294e145d4d8d936fba2b49bb76b36 Mon Sep 17 00:00:00 2001 From: Ruifeng Zheng Date: Fri, 27 Feb 2026 09:16:27 +0800 Subject: [PATCH 067/130] [SPARK-55713][PYTHON][TESTS] Add `LongArrowToPandasBenchmark` for long type conversions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? Add benchmark for long type conversions ### Why are the changes needed? to check the performance of critical code path ### Does this PR introduce _any_ user-facing change? no, test-only ### How was this patch tested? manually check for now, the ASV is not yet set up in CI ```sh (spark-dev-313) ➜ benchmarks git:(update_benchmark_null_int) asv run --python=same --quick -b 'bench_arrow.LongArrowToPandasBenchmark' · Discovering benchmarks · Running 2 total benchmarks (1 commits * 1 environments * 2 benchmarks) [ 0.00%] ·· Benchmarking existing-py_Users_ruifeng.zheng_.dev_miniconda3_envs_spark-dev-313_bin_python3.13 [25.00%] ··· bench_arrow.LongArrowToPandasBenchmark.peakmem_long_to_pandas ok [25.00%] ··· ========= ======== ==================== =========== -- method --------- ----------------------------------------- n_rows simple arrow_types_mapper pd.Series ========= ======== ==================== =========== 10000 109M 110M 111M 100000 117M 115M 110M 1000000 164M 165M 165M ========= ======== ==================== =========== [50.00%] ··· bench_arrow.LongArrowToPandasBenchmark.time_long_to_pandas ok [50.00%] ··· ========= ========= ==================== =========== -- method --------- ------------------------------------------ n_rows simple arrow_types_mapper pd.Series ========= ========= ==================== =========== 10000 131±0μs 310±0μs 162±0μs 100000 134±0μs 482±0μs 173±0μs 1000000 155±0μs 1.35±0ms 273±0μs ========= ========= ==================== =========== (spark-dev-313) ➜ benchmarks git:(update_benchmark_null_int) asv run --python=same --quick -b 'bench_arrow.NullableLongArrowToPandasBenchmark' · Discovering benchmarks · Running 2 total benchmarks (1 commits * 1 environments * 2 benchmarks) [ 0.00%] ·· Benchmarking existing-py_Users_ruifeng.zheng_.dev_miniconda3_envs_spark-dev-313_bin_python3.13 [25.00%] ··· bench_arrow.NullableLongArrowToPandasBenchmark.peakmem_long_with_nulls_to_pandas_ext ok [25.00%] ··· ========= ====================== ==================== =========== -- method --------- ------------------------------------------------------- n_rows integer_object_nulls arrow_types_mapper pd.Series ========= ====================== ==================== =========== 10000 110M 110M 108M 100000 132M 115M 113M 1000000 246M 201M 201M ========= ====================== ==================== =========== [50.00%] ··· bench_arrow.NullableLongArrowToPandasBenchmark.time_long_with_nulls_to_pandas_ext ok [50.00%] ··· ========= ====================== ==================== =========== -- method --------- ------------------------------------------------------- n_rows integer_object_nulls arrow_types_mapper pd.Series ========= ====================== ==================== =========== 10000 1.49±0ms 1.81±0ms 3.19±0ms 100000 13.2±0ms 12.2±0ms 30.0±0ms 1000000 158±0ms 123±0ms 296±0ms ========= ====================== ==================== =========== ``` ### Was this patch authored or co-authored using generative AI tooling? no Closes #54513 from zhengruifeng/update_benchmark_null_int. Authored-by: Ruifeng Zheng Signed-off-by: Ruifeng Zheng --- python/benchmarks/bench_arrow.py | 65 ++++++++++++++++++++++++++++++++ python/pyspark/sql/conversion.py | 28 +------------- 2 files changed, 66 insertions(+), 27 deletions(-) diff --git a/python/benchmarks/bench_arrow.py b/python/benchmarks/bench_arrow.py index 9791e2cdf1d0f..7ace66f229654 100644 --- a/python/benchmarks/bench_arrow.py +++ b/python/benchmarks/bench_arrow.py @@ -51,3 +51,68 @@ def peakmem_int_to_pandas(self, n_rows, types_mapper): def peakmem_int_with_nulls_to_pandas(self, n_rows, types_mapper): self.int_array_with_nulls.to_pandas(types_mapper=self.types_mapper) + + +class LongArrowToPandasBenchmark: + """Benchmark for Arrow long array -> Pandas conversions.""" + + params = [ + [10000, 100000, 1000000], + ["simple", "arrow_types_mapper", "pd.Series"], + ] + param_names = ["n_rows", "method"] + + def setup(self, n_rows, method): + self.long_array = pa.array(list(range(n_rows - 1)) + [9223372036854775707], type=pa.int64()) + + # check 3 different ways to convert non-nullable longs to numpy int64 + def run_long_to_pandas(self, n_rows, method): + if method == "simple": + ser = self.long_array.to_pandas() + elif method == "arrow_types_mapper": + ser = self.long_array.to_pandas(types_mapper=pd.ArrowDtype).astype(np.int64) + else: + ser = pd.Series(self.long_array, dtype=np.int64) + assert ser.dtype == np.int64 + + def time_long_to_pandas(self, n_rows, method): + self.run_long_to_pandas(n_rows, method) + + def peakmem_long_to_pandas(self, n_rows, method): + self.run_long_to_pandas(n_rows, method) + + +class NullableLongArrowToPandasBenchmark: + """Benchmark for Arrow long array with nulls -> Pandas conversions.""" + + params = [ + [10000, 100000, 1000000], + ["integer_object_nulls", "arrow_types_mapper", "pd.Series"], + ] + param_names = ["n_rows", "method"] + + def setup(self, n_rows, method): + self.long_array_with_nulls = pa.array( + [i if i % 10 != 0 else None for i in range(n_rows - 1)] + [9223372036854775707], + type=pa.int64(), + ) + + # check 3 different ways to convert nullable longs to nullable extension type + def run_long_with_nulls_to_pandas_ext(self, n_rows, method): + if method == "integer_object_nulls": + ser = self.long_array_with_nulls.to_pandas(integer_object_nulls=True).astype( + pd.Int64Dtype() + ) + elif method == "arrow_types_mapper": + ser = self.long_array_with_nulls.to_pandas(types_mapper=pd.ArrowDtype).astype( + pd.Int64Dtype() + ) + else: + ser = pd.Series(self.long_array_with_nulls.to_pylist(), dtype=pd.Int64Dtype()) + assert ser.dtype == pd.Int64Dtype() + + def time_long_with_nulls_to_pandas_ext(self, n_rows, method): + self.run_long_with_nulls_to_pandas_ext(n_rows, method) + + def peakmem_long_with_nulls_to_pandas_ext(self, n_rows, method): + self.run_long_with_nulls_to_pandas_ext(n_rows, method) diff --git a/python/pyspark/sql/conversion.py b/python/pyspark/sql/conversion.py index 34e047ae52d5f..e0708716a46c1 100644 --- a/python/pyspark/sql/conversion.py +++ b/python/pyspark/sql/conversion.py @@ -1654,33 +1654,7 @@ def convert_numpy( series: pd.Series - # TODO(SPARK-55332): Create benchmark for pa.array -> pd.series integer conversion - # 1, benchmark a nullable integral array - # a = pa.array(list(range(10000000)) + [9223372036854775707, None], type=pa.int64()) - # %timeit a.to_pandas(types_mapper=pd.ArrowDtype) - # 11.9 μs ± 407 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each) - # %timeit a.to_pandas(types_mapper=pd.ArrowDtype).astype(pd.Int64Dtype()) - # 589 ms ± 9.35 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) - # %timeit pd.Series(a.to_pylist(), dtype=pd.Int64Dtype()) - # 2.94 s ± 19.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) - # %timeit a.to_pandas(integer_object_nulls=True).astype(pd.Int64Dtype()) - # 2.05 s ± 22.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) - # pd.Series(a, dtype=pd.Int64Dtype()) - # fails due to internal np.float64 coercion - # OverflowError: Python int too large to convert to C long - # - # 2, benchmark a nullable integral array - # b = pa.array(list(range(10000000)) + [9223372036854775707, 1], type=pa.int64()) - # %timeit b.to_pandas(types_mapper=pd.ArrowDtype).astype(np.int64) - # 30.2 μs ± 831 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each) - # %timeit pd.Series(b.to_pandas(types_mapper=pd.ArrowDtype), dtype=np.int64) - # 33.3 μs ± 928 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each) - # %timeit pd.Series(b, dtype=np.int64) <- lose the name - # 11.9 μs ± 125 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each) - # %timeit b.to_pandas() - # 7.56 μs ± 96.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each) - # %timeit b.to_pandas().astype(np.int64) <- astype is non-trivial - # 19.1 μs ± 242 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each) + # conversion methods are selected based on benchmark python/benchmarks/bench_arrow.py if isinstance(spark_type, ByteType): if arr.null_count > 0: series = arr.to_pandas(types_mapper=pd.ArrowDtype).astype(pd.Int8Dtype()) From df1378e00966b56ce0b95376fed0179ce5fe51c1 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Thu, 26 Feb 2026 18:04:08 -0800 Subject: [PATCH 068/130] [SPARK-55725][K8S][DOCS] Make `AbstractPodsAllocator` docs up-to-date ### What changes were proposed in this pull request? This PR aims to make `AbstractPodsAllocator` documentation up-to-date: - Use `Javadoc` style instead of `Scaladoc` according to the [Apache Spark Code Style Guide](https://spark.apache.org/contributing.html). - Add `Since` annotation for the class and methods. - Update the class documentation with new `DeploymentPodsAllocator`. - Update the method documentation with `since` tag. ### Why are the changes needed? `AbstractPodsAllocator` is one of `DeveloperApi` of the Apache Spark. https://github.com/apache/spark/blob/4da26e4bf9eab119ff2489c5fdf85efe60f6f469/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/AbstractPodsAllocator.scala#L36-L37 Recently, Apache Spark 4.2.0 - Added a new built-in implementation, `DeploymentPodsAllocator`. - #52867 - Added new API, `setExecutorPodsLifecycleManager`. - #53840 ### Does this PR introduce _any_ user-facing change? No, this changes documentations only. ### How was this patch tested? Manual review. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54526 from dongjoon-hyun/SPARK-55725. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- .../cluster/k8s/AbstractPodsAllocator.scala | 49 ++++++++++++++----- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/AbstractPodsAllocator.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/AbstractPodsAllocator.scala index 8803d3d031e47..cae58c34a185a 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/AbstractPodsAllocator.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/AbstractPodsAllocator.scala @@ -18,7 +18,7 @@ package org.apache.spark.scheduler.cluster.k8s import io.fabric8.kubernetes.api.model.Pod -import org.apache.spark.annotation.DeveloperApi +import org.apache.spark.annotation.{DeveloperApi, Since} import org.apache.spark.resource.ResourceProfile @@ -26,47 +26,72 @@ import org.apache.spark.resource.ResourceProfile * :: DeveloperApi :: * A abstract interface for allowing different types of pods allocation. * - * The internal Spark implementations are [[StatefulSetPodsAllocator]] - * and [[ExecutorPodsAllocator]]. This may be useful for folks integrating with custom schedulers. - * - * This API may change or be removed at anytime. + * The internal Spark implementations are [[StatefulSetPodsAllocator]], + * [[DeploymentPodsAllocator]], and [[ExecutorPodsAllocator]]. + * This may be useful for folks integrating with custom schedulers. * * @since 3.3.0 */ @DeveloperApi +@Since("3.3.0") abstract class AbstractPodsAllocator { - /* + /** * Optional lifecycle manager for tracking executor pod lifecycle events. * Set via setExecutorPodsLifecycleManager for backward compatibility. + * + * @since 4.2.0 */ + @Since("4.2.0") protected var executorPodsLifecycleManager: Option[ExecutorPodsLifecycleManager] = None - /* + /** * Set the lifecycle manager for tracking executor pod lifecycle events. * This method is optional and may not exist in custom implementations based on older versions. + * + * @since 4.2.0 */ + @Since("4.2.0") def setExecutorPodsLifecycleManager(manager: ExecutorPodsLifecycleManager): Unit = { executorPodsLifecycleManager = Some(manager) } - /* + /** * Set the total expected executors for an application + * + * @since 3.3.0 */ + @Since("3.3.0") def setTotalExpectedExecutors(resourceProfileToTotalExecs: Map[ResourceProfile, Int]): Unit - /* + + /** * Reference to driver pod. + * + * @since 3.3.0 */ + @Since("3.3.0") def driverPod: Option[Pod] - /* + + /** * If the pod for a given exec id is deleted. + * + * @since 3.3.0 */ + @Since("3.3.0") def isDeleted(executorId: String): Boolean - /* + + /** * Start hook. + * + * @since 3.3.0 */ + @Since("3.3.0") def start(applicationId: String, schedulerBackend: KubernetesClusterSchedulerBackend): Unit - /* + + /** * Stop hook + * + * @since 3.3.0 */ + @Since("3.3.0") def stop(applicationId: String): Unit } From 8026f7d222489a412bcb781f49d414302b593a9b Mon Sep 17 00:00:00 2001 From: Yuchen Liu <170372783+eason-yuchen-liu@users.noreply.github.com> Date: Fri, 27 Feb 2026 13:21:03 +0900 Subject: [PATCH 069/130] [SPARK-55699][SS] Inconsistent reading of LowLatencyClock when used together with ManualClock ### What changes were proposed in this pull request? This PR updates the signature of `nextWithTimeout` in Streaming Real-Time Mode sources. We add a new parameter `startTime`, which is used to pass the start time used by `LowLatencyReaderWrap` to the each source. This ensures that the starting time used by the streaming engine and the source connector are the same. ### Why are the changes needed? There was an issue that RTM tests that use manual clock might stuck because manual clock advancement may happens right in between `LowLatencyReaderWrap` getting the reference time, and `nextWithTimeout` in each source getting the start time. `nextWithTimeout` may uses the already advanced time to time its wait. When this happens, since the manual clock may only be advanced once by the test, `nextWithTimeout` may never return, causing test timeout. This only affects LowLatencyMemoryStream when using together with manual clocks. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Existing unit tests. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54497 from eason-yuchen-liu/fixLowLatencyClockInconsistency. Authored-by: Yuchen Liu <170372783+eason-yuchen-liu@users.noreply.github.com> Signed-off-by: Jungtaek Lim --- .../spark/sql/kafka010/KafkaBatchPartitionReader.scala | 3 ++- .../connector/read/streaming/SupportsRealTimeRead.java | 5 ++++- .../execution/datasources/v2/RealTimeStreamScanExec.scala | 2 +- .../streaming/sources/LowLatencyMemoryStream.scala | 8 ++++++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/connector/kafka-0-10-sql/src/main/scala/org/apache/spark/sql/kafka010/KafkaBatchPartitionReader.scala b/connector/kafka-0-10-sql/src/main/scala/org/apache/spark/sql/kafka010/KafkaBatchPartitionReader.scala index 9fcdf1a7d9bf4..77ebcb04f2f76 100644 --- a/connector/kafka-0-10-sql/src/main/scala/org/apache/spark/sql/kafka010/KafkaBatchPartitionReader.scala +++ b/connector/kafka-0-10-sql/src/main/scala/org/apache/spark/sql/kafka010/KafkaBatchPartitionReader.scala @@ -104,7 +104,8 @@ private case class KafkaBatchPartitionReader( } } - override def nextWithTimeout(timeoutMs: java.lang.Long): RecordStatus = { + override def nextWithTimeout( + startTime: java.lang.Long, timeoutMs: java.lang.Long): RecordStatus = { if (!iteratorForRealTimeMode.isDefined) { logInfo(s"Getting a new kafka consuming iterator for ${offsetRange.topicPartition} " + s"starting from ${nextOffset}, timeoutMs ${timeoutMs}") diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/streaming/SupportsRealTimeRead.java b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/streaming/SupportsRealTimeRead.java index 5bed945432c95..1e939c14cdc96 100644 --- a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/streaming/SupportsRealTimeRead.java +++ b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/read/streaming/SupportsRealTimeRead.java @@ -78,9 +78,12 @@ public Optional recArrivalTime() { * Alternative function to be called than next(), that proceed to the next record. The different * from next() is that, if there is no more records, the call needs to keep waiting until * the timeout. + * @param startTime the base time (milliseconds) the was used to calculate the timeout. + * Sources should use it as the reference time to start waiting for the next + * record instead of getting the latest time from LowLatencyClock. * @param timeout if no result is available after this timeout (milliseconds), return * @return {@link RecordStatus} describing whether a record is available and its arrival time * @throws IOException */ - RecordStatus nextWithTimeout(Long timeout) throws IOException; + RecordStatus nextWithTimeout(Long startTime, Long timeout) throws IOException; } diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/RealTimeStreamScanExec.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/RealTimeStreamScanExec.scala index 3432f28e12cc2..9fff2d91af14c 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/RealTimeStreamScanExec.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/RealTimeStreamScanExec.scala @@ -66,7 +66,7 @@ case class LowLatencyReaderWrap( val ret = if (curTime >= lowLatencyEndTime) { RecordStatus.newStatusWithoutArrivalTime(false) } else { - reader.nextWithTimeout(lowLatencyEndTime - curTime) + reader.nextWithTimeout(curTime, lowLatencyEndTime - curTime) } if (!ret.hasRecord) { diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/sources/LowLatencyMemoryStream.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/sources/LowLatencyMemoryStream.scala index 0e34b46a56c58..bc8f51c95861d 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/sources/LowLatencyMemoryStream.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/sources/LowLatencyMemoryStream.scala @@ -277,8 +277,12 @@ class LowLatencyMemoryStreamPartitionReader( if (TaskContext.get() == null) { throw new IllegalStateException("Task context was not set!") } - override def nextWithTimeout(timeout: java.lang.Long): RecordStatus = { - val startReadTime = clock.nanoTime() + override def nextWithTimeout( + startTime: java.lang.Long, timeout: java.lang.Long): RecordStatus = { + // SPARK-55699: Use the reference time passed in by the caller instead of getting the latest + // time from LowLatencyClock, to avoid inconsistent reading when LowLatencyClock is a + // manual clock. + val startReadTime = startTime var elapsedTimeMs = 0L current = getRecordWithTimestamp while (current.isEmpty) { From 7182a79d70da46490aafb4f73d84112cb7583e71 Mon Sep 17 00:00:00 2001 From: Ruifeng Zheng Date: Fri, 27 Feb 2026 12:34:40 +0800 Subject: [PATCH 070/130] [SPARK-55463][PYTHON][FOLLOW-UP] Delete unnecessary `date_as_object=True` in VariantType conversion ### What changes were proposed in this pull request? Delete unnecessary `date_as_object=True` ### Why are the changes needed? 1, VariantType is not supposed to include any date fields; 2, `date_as_object` actually defaults to True, according to the [API reference](https://arrow.apache.org/docs/python/generated/pyarrow.Array.html#pyarrow.Array.to_pandas) Remove it to be consistent with changes from https://github.com/apache/spark/pull/54303/changes ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? CI ### Was this patch authored or co-authored using generative AI tooling? Closes #54509 from zhengruifeng/del_date_obj. Authored-by: Ruifeng Zheng Signed-off-by: Ruifeng Zheng --- python/pyspark/sql/conversion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pyspark/sql/conversion.py b/python/pyspark/sql/conversion.py index e0708716a46c1..c10e7173cb57c 100644 --- a/python/pyspark/sql/conversion.py +++ b/python/pyspark/sql/conversion.py @@ -1705,7 +1705,7 @@ def convert_numpy( else None ) elif isinstance(spark_type, VariantType): - series = arr.to_pandas(date_as_object=True) + series = arr.to_pandas() series = series.map( lambda v: VariantVal(v["value"], v["metadata"]) if v is not None else None ) From 2996e3012b50dffe7c6ceac012ce1b45c3e12f05 Mon Sep 17 00:00:00 2001 From: Ruifeng Zheng Date: Fri, 27 Feb 2026 12:35:46 +0800 Subject: [PATCH 071/130] [MINOR][PYTHON] Add `asv` in `dev/requirements.txt` ### What changes were proposed in this pull request? Add `asv` in `dev/requirements.txt` ### Why are the changes needed? `asv` is used to run the benchmark locally ### Does this PR introduce _any_ user-facing change? no, dev-only ### How was this patch tested? ci ### Was this patch authored or co-authored using generative AI tooling? no Closes #54530 from zhengruifeng/require_asv. Authored-by: Ruifeng Zheng Signed-off-by: Ruifeng Zheng --- dev/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/requirements.txt b/dev/requirements.txt index b6bf9a693c024..a219a017cf92f 100644 --- a/dev/requirements.txt +++ b/dev/requirements.txt @@ -19,6 +19,7 @@ unittest-xml-reporting openpyxl # PySpark test dependencies (optional) +asv coverage tabulate From fcf8636105c060b0cc05712d503d4f6fe5a5dff5 Mon Sep 17 00:00:00 2001 From: Jungtaek Lim Date: Fri, 27 Feb 2026 13:58:53 +0900 Subject: [PATCH 072/130] [SPARK-55144][SS] Introduce new state format version for performant stream-stream join ### What changes were proposed in this pull request? This PR proposes to implement the new state format for stream-stream join, based on the new state key encoding w.r.t. event time awareness. The new state format is focused to eliminate the necessity of full scan during eviction & populating unmatched rows. The overhead of eviction should have bound to the actual number of state rows to be evicted (indirectly impacted by the amount of watermark advancement), but we have been doing the full scan with the existing state format, which could take more than 2 seconds in 1,000,000 rows even if there is zero row to be evicted. The overhead of eviction with the new state format would be bound to the actual number of state rows to be evicted, taking around 30ms or even less in 1,000,000 rows when there is zero row to be evicted. To achieve the above, we make a drastic change of data structure to move out from the logical array, and introduce a secondary index in addition to the main data. Each side of the join will use two (virtual) column families (total 4 column families), which are following: * KeyWithTsToValuesStore * Primary data store * (key, event time) -> values * each element in values consists of (value, matched) * TsWithKeyTypeStore * Secondary index for efficient eviction * (event time, key) -> empty value (configured as multi-values) * numValues is calculated by the number of elements in the value side; new element is added when a new value is added into values in primary data store * This is to track the number of deleted rows accurately. It's optional but the metric has been useful so we want to keep it as it is. As the format of key part implies, KeyWithTsToValuesStore will use `TimestampAsPostfixKeyStateEncoderSpec`, and TsWithKeyTypeStore will use `TimestampAsPrefixKeyStateEncoderSpec`. The granularity of the timestamp for event time is 1 millisecond, which is in line with the granularity for watermark advancement. This can be a kind of knob controlling the number of the keys vs the number of the values in the key, trading off the granularity of eviction based on watermark advancement vs the size of key space (may impact performance). There are several follow-ups with this state format implementation, which can be addressed on top of this: * further optimizations with RocksDB offering: WriteBatch (for batched writes), MGET, etc. * retrieving matched rows with the "scope" of timestamps (in time-interval join) * while the format is ready to support ordered scan of timestamp, this needs another state store API to define the range of keys to scan, which needs some effort * Do not update the matched flag for non-outer join side. ### Why are the changes needed? The cost of eviction based on full scan is severe to make the stream-stream join to be lower latency. Also, the logic of maintaining logical array is complicated enough to maintain and the performance characteristic is less predictable given the behavior of deleting the element in random index (placing the value of the last index to the deleted index). ### Does this PR introduce _any_ user-facing change? No. At this point, this state format is not integrated with the actual stream-stream join operator, and we need to do follow-up work for integration to finally introduce the change to user-facing. ### How was this patch tested? New UT suites, refactoring the existing suite to test with both time window and time interval cases. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #53930 from HeartSaVioR/SPARK-55144-on-top-of-SPARK-55129. Authored-by: Jungtaek Lim Signed-off-by: Jungtaek Lim --- .../apache/spark/sql/internal/SQLConf.scala | 5 +- .../join/StreamingSymmetricHashJoinExec.scala | 91 +- .../StreamingSymmetricHashJoinHelper.scala | 18 +- ...ngSymmetricHashJoinValueRowConverter.scala | 118 +++ .../join/SymmetricHashJoinStateManager.scala | 957 ++++++++++++++++-- .../stateful/statefulOperators.scala | 38 + .../SymmetricHashJoinStateManagerSuite.scala | 896 +++++++++++----- 7 files changed, 1747 insertions(+), 376 deletions(-) create mode 100644 sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinValueRowConverter.scala diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala index b2a2b7027394f..1874ff195516b 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala @@ -3087,9 +3087,12 @@ object SQLConf { .doc("State format version used by streaming join operations in a streaming query. " + "State between versions are tend to be incompatible, so state format version shouldn't " + "be modified after running. Version 3 uses a single state store with virtual column " + - "families instead of four stores and is only supported with RocksDB.") + "families instead of four stores and is only supported with RocksDB. NOTE: version " + + "1 is DEPRECATED and should not be explicitly set by users.") .version("3.0.0") .intConf + // TODO: [SPARK-55628] Add version 4 once we integrate the state format version 4 into + // stream-stream join operator. .checkValue(v => Set(1, 2, 3).contains(v), "Valid versions are 1, 2, and 3") .createWithDefault(2) diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinExec.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinExec.scala index ef37185ce4166..d8ad576bb68a1 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinExec.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinExec.scala @@ -433,7 +433,7 @@ case class StreamingSymmetricHashJoinExec( } val initIterFn = { () => - val removedRowIter = joinerManager.leftSideJoiner.removeOldState() + val removedRowIter = joinerManager.leftSideJoiner.removeAndReturnOldState() removedRowIter.filterNot { kv => stateFormatVersion match { case 1 => matchesWithRightSideState(new UnsafeRowPair(kv.key, kv.value)) @@ -459,7 +459,7 @@ case class StreamingSymmetricHashJoinExec( } val initIterFn = { () => - val removedRowIter = joinerManager.rightSideJoiner.removeOldState() + val removedRowIter = joinerManager.rightSideJoiner.removeAndReturnOldState() removedRowIter.filterNot { kv => stateFormatVersion match { case 1 => matchesWithLeftSideState(new UnsafeRowPair(kv.key, kv.value)) @@ -484,13 +484,13 @@ case class StreamingSymmetricHashJoinExec( } val leftSideInitIterFn = { () => - val removedRowIter = joinerManager.leftSideJoiner.removeOldState() + val removedRowIter = joinerManager.leftSideJoiner.removeAndReturnOldState() removedRowIter.filterNot(isKeyToValuePairMatched) .map(pair => joinedRow.withLeft(pair.value).withRight(nullRight)) } val rightSideInitIterFn = { () => - val removedRowIter = joinerManager.rightSideJoiner.removeOldState() + val removedRowIter = joinerManager.rightSideJoiner.removeAndReturnOldState() removedRowIter.filterNot(isKeyToValuePairMatched) .map(pair => joinedRow.withLeft(nullLeft).withRight(pair.value)) } @@ -539,22 +539,19 @@ case class StreamingSymmetricHashJoinExec( // the outer side (e.g., left side for left outer join) while generating the outer "null" // outputs. Now, we have to remove unnecessary state rows from the other side (e.g., right // side for the left outer join) if possible. In all cases, nothing needs to be outputted, - // hence the removal needs to be done greedily by immediately consuming the returned - // iterator. + // hence the removal needs to be done greedily. // // For full outer joins, we have already removed unnecessary states from both sides, so // nothing needs to be outputted here. - val cleanupIter = joinType match { - case Inner | LeftSemi => joinerManager.removeOldState() - case LeftOuter => joinerManager.rightSideJoiner.removeOldState() - case RightOuter => joinerManager.leftSideJoiner.removeOldState() - case FullOuter => Iterator.empty - case _ => throwBadJoinTypeException() - } - while (cleanupIter.hasNext) { - cleanupIter.next() - numRemovedStateRows += 1 - } + numRemovedStateRows += ( + joinType match { + case Inner | LeftSemi => joinerManager.removeOldState() + case LeftOuter => joinerManager.rightSideJoiner.removeOldState() + case RightOuter => joinerManager.leftSideJoiner.removeOldState() + case FullOuter => 0L + case _ => throwBadJoinTypeException() + } + ) } // Commit all state changes and update state store metrics @@ -643,7 +640,7 @@ case class StreamingSymmetricHashJoinExec( private[this] val keyGenerator = UnsafeProjection.create(joinKeys, inputAttributes) private[this] val stateKeyWatermarkPredicateFunc = stateWatermarkPredicate match { - case Some(JoinStateKeyWatermarkPredicate(expr)) => + case Some(JoinStateKeyWatermarkPredicate(expr, _)) => // inputSchema can be empty as expr should only have BoundReferences and does not require // the schema to generated predicate. See [[StreamingSymmetricHashJoinHelper]]. Predicate.create(expr, Seq.empty).eval _ @@ -652,7 +649,7 @@ case class StreamingSymmetricHashJoinExec( } private[this] val stateValueWatermarkPredicateFunc = stateWatermarkPredicate match { - case Some(JoinStateValueWatermarkPredicate(expr)) => + case Some(JoinStateValueWatermarkPredicate(expr, _)) => Predicate.create(expr, inputAttributes).eval _ case _ => Predicate.create(Literal(false), Seq.empty).eval _ // false = do not remove if no predicate @@ -792,6 +789,32 @@ case class StreamingSymmetricHashJoinExec( joinStateManager.get(key) } + /** + * Remove the old state key-value pairs from this joiner's state manager based on the state + * watermark predicate, and return the number of removed rows. + */ + def removeOldState(): Long = { + stateWatermarkPredicate match { + case Some(JoinStateKeyWatermarkPredicate(_, stateWatermark)) => + joinStateManager match { + case s: SupportsEvictByCondition => + s.evictByKeyCondition(stateKeyWatermarkPredicateFunc) + + case s: SupportsEvictByTimestamp => + s.evictByTimestamp(stateWatermark) + } + case Some(JoinStateValueWatermarkPredicate(_, stateWatermark)) => + joinStateManager match { + case s: SupportsEvictByCondition => + s.evictByValueCondition(stateValueWatermarkPredicateFunc) + + case s: SupportsEvictByTimestamp => + s.evictByTimestamp(stateWatermark) + } + case _ => 0L + } + } + /** * Builds an iterator over old state key-value pairs, removing them lazily as they're produced. * @@ -802,12 +825,24 @@ case class StreamingSymmetricHashJoinExec( * We do this to avoid requiring either two passes or full materialization when * processing the rows for outer join. */ - def removeOldState(): Iterator[KeyToValuePair] = { + def removeAndReturnOldState(): Iterator[KeyToValuePair] = { stateWatermarkPredicate match { - case Some(JoinStateKeyWatermarkPredicate(expr)) => - joinStateManager.removeByKeyCondition(stateKeyWatermarkPredicateFunc) - case Some(JoinStateValueWatermarkPredicate(expr)) => - joinStateManager.removeByValueCondition(stateValueWatermarkPredicateFunc) + case Some(JoinStateKeyWatermarkPredicate(_, stateWatermark)) => + joinStateManager match { + case s: SupportsEvictByCondition => + s.evictAndReturnByKeyCondition(stateKeyWatermarkPredicateFunc) + + case s: SupportsEvictByTimestamp => + s.evictAndReturnByTimestamp(stateWatermark) + } + case Some(JoinStateValueWatermarkPredicate(_, stateWatermark)) => + joinStateManager match { + case s: SupportsEvictByCondition => + s.evictAndReturnByValueCondition(stateValueWatermarkPredicateFunc) + + case s: SupportsEvictByTimestamp => + s.evictAndReturnByTimestamp(stateWatermark) + } case _ => Iterator.empty } } @@ -836,8 +871,12 @@ case class StreamingSymmetricHashJoinExec( private case class OneSideHashJoinerManager( leftSideJoiner: OneSideHashJoiner, rightSideJoiner: OneSideHashJoiner) { - def removeOldState(): Iterator[KeyToValuePair] = { - leftSideJoiner.removeOldState() ++ rightSideJoiner.removeOldState() + def removeOldState(): Long = { + leftSideJoiner.removeOldState() + rightSideJoiner.removeOldState() + } + + def removeAndReturnOldState(): Iterator[KeyToValuePair] = { + leftSideJoiner.removeAndReturnOldState() ++ rightSideJoiner.removeAndReturnOldState() } def metrics: StateStoreMetrics = { diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinHelper.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinHelper.scala index 7b02a43cd5a9f..a916b0d626d3e 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinHelper.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinHelper.scala @@ -46,12 +46,12 @@ object StreamingSymmetricHashJoinHelper extends Logging { override def toString: String = s"$desc: $expr" } /** Predicate for watermark on state keys */ - case class JoinStateKeyWatermarkPredicate(expr: Expression) + case class JoinStateKeyWatermarkPredicate(expr: Expression, stateWatermark: Long) extends JoinStateWatermarkPredicate { def desc: String = "key predicate" } /** Predicate for watermark on state values */ - case class JoinStateValueWatermarkPredicate(expr: Expression) + case class JoinStateValueWatermarkPredicate(expr: Expression, stateWatermark: Long) extends JoinStateWatermarkPredicate { def desc: String = "value predicate" } @@ -212,8 +212,11 @@ object StreamingSymmetricHashJoinHelper extends Logging { oneSideJoinKeys(joinKeyOrdinalForWatermark.get).dataType, oneSideJoinKeys(joinKeyOrdinalForWatermark.get).nullable) val expr = watermarkExpression(Some(keyExprWithWatermark), eventTimeWatermarkForEviction) - expr.map(JoinStateKeyWatermarkPredicate.apply _) - + expr.map { e => + // watermarkExpression only provides the expression when eventTimeWatermarkForEviction + // is defined + JoinStateKeyWatermarkPredicate(e, eventTimeWatermarkForEviction.get) + } } else if (isWatermarkDefinedOnInput) { // case 2 in the StreamingSymmetricHashJoinExec docs val stateValueWatermark = StreamingJoinHelper.getStateValueWatermark( attributesToFindStateWatermarkFor = AttributeSet(oneSideInputAttributes), @@ -222,8 +225,11 @@ object StreamingSymmetricHashJoinHelper extends Logging { eventTimeWatermarkForEviction) val inputAttributeWithWatermark = oneSideInputAttributes.find(_.metadata.contains(delayKey)) val expr = watermarkExpression(inputAttributeWithWatermark, stateValueWatermark) - expr.map(JoinStateValueWatermarkPredicate.apply _) - + expr.map { e => + // watermarkExpression only provides the expression when eventTimeWatermarkForEviction + // is defined + JoinStateValueWatermarkPredicate(e, stateValueWatermark.get) + } } else { None } diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinValueRowConverter.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinValueRowConverter.scala new file mode 100644 index 0000000000000..b4258125bf899 --- /dev/null +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/StreamingSymmetricHashJoinValueRowConverter.scala @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.spark.sql.execution.streaming.operators.stateful.join + +import org.apache.spark.sql.catalyst.expressions.{Attribute, AttributeReference, Literal, UnsafeProjection, UnsafeRow} +import org.apache.spark.sql.execution.streaming.operators.stateful.join.SymmetricHashJoinStateManager.ValueAndMatchPair +import org.apache.spark.sql.types.BooleanType + +/** + * Converter between the value row stored in state store and the (actual value, match) pair. + */ +trait StreamingSymmetricHashJoinValueRowConverter { + /** Defines the schema of the value row (the value side of K-V in state store). */ + def valueAttributes: Seq[Attribute] + + /** + * Convert the value row to (actual value, match) pair. + * + * NOTE: implementations should ensure the result row is NOT reused during execution, so + * that caller can safely read the value in any time. + */ + def convertValue(value: UnsafeRow): ValueAndMatchPair + + /** + * Build the value row from (actual value, match) pair. This is expected to be called just + * before storing to the state store. + * + * NOTE: depending on the implementation, the result row "may" be reused during execution + * (to avoid initialization of object), so the caller should ensure that the logic doesn't + * get affected by such behavior. Call copy() against the result row if needed. + */ + def convertToValueRow(value: UnsafeRow, matched: Boolean): UnsafeRow +} + +/** + * V1 implementation of the converter, which simply stores the actual value in state store and + * treats the match status as false. Note that only state format version 1 uses this converter, + * and this is only for backward compatibility. There is known correctness issue for outer join + * with this converter - see SPARK-26154 for more details. + */ +class StreamingSymmetricHashJoinValueRowConverterFormatV1( + inputValueAttributes: Seq[Attribute]) extends StreamingSymmetricHashJoinValueRowConverter { + override val valueAttributes: Seq[Attribute] = inputValueAttributes + + override def convertValue(value: UnsafeRow): ValueAndMatchPair = + if (value != null) ValueAndMatchPair(value, false) else null + + override def convertToValueRow(value: UnsafeRow, matched: Boolean): UnsafeRow = value +} + +/** + * V2 implementation of the converter, which adds an extra boolean field to store the match status + * in state store. This is the default implementation for state format version 2 and above, which + * fixes the correctness issue for outer join in V1 implementation. + */ +class StreamingSymmetricHashJoinValueRowConverterFormatV2( + inputValueAttributes: Seq[Attribute]) extends StreamingSymmetricHashJoinValueRowConverter { + private val valueWithMatchedExprs = inputValueAttributes :+ Literal(true) + private val indexOrdinalInValueWithMatchedRow = inputValueAttributes.size + + private val valueWithMatchedRowGenerator = UnsafeProjection.create(valueWithMatchedExprs, + inputValueAttributes) + + override val valueAttributes: Seq[Attribute] = inputValueAttributes :+ + AttributeReference("matched", BooleanType)() + + // Projection to generate key row from (value + matched) row + private val valueRowGenerator = UnsafeProjection.create( + inputValueAttributes, valueAttributes) + + override def convertValue(value: UnsafeRow): ValueAndMatchPair = { + if (value != null) { + ValueAndMatchPair(valueRowGenerator(value).copy(), + value.getBoolean(indexOrdinalInValueWithMatchedRow)) + } else { + null + } + } + + override def convertToValueRow(value: UnsafeRow, matched: Boolean): UnsafeRow = { + val row = valueWithMatchedRowGenerator(value) + row.setBoolean(indexOrdinalInValueWithMatchedRow, matched) + row + } +} + +/** + * The entry point to create the converter for value row in state store. The converter is created + * based on the state format version. + */ +object StreamingSymmetricHashJoinValueRowConverter { + def create( + inputValueAttributes: Seq[Attribute], + stateFormatVersion: Int): StreamingSymmetricHashJoinValueRowConverter = { + stateFormatVersion match { + case 1 => new StreamingSymmetricHashJoinValueRowConverterFormatV1(inputValueAttributes) + case 2 | 3 | 4 => + new StreamingSymmetricHashJoinValueRowConverterFormatV2(inputValueAttributes) + case _ => throw new IllegalArgumentException ("Incorrect state format version! " + + s"version $stateFormatVersion") + } + } +} diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/SymmetricHashJoinStateManager.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/SymmetricHashJoinStateManager.scala index 49d08d52b3bf1..9aa41e1966591 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/SymmetricHashJoinStateManager.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/join/SymmetricHashJoinStateManager.scala @@ -27,16 +27,736 @@ import org.apache.spark.TaskContext import org.apache.spark.internal.Logging import org.apache.spark.internal.LogKeys.{END_INDEX, START_INDEX, STATE_STORE_ID} import org.apache.spark.sql.catalyst.InternalRow -import org.apache.spark.sql.catalyst.expressions.{Attribute, AttributeReference, Expression, JoinedRow, Literal, SafeProjection, SpecificInternalRow, UnsafeProjection, UnsafeRow} +import org.apache.spark.sql.catalyst.expressions.{Attribute, AttributeReference, Expression, JoinedRow, Literal, NamedExpression, SafeProjection, SpecificInternalRow, UnsafeProjection, UnsafeRow} +import org.apache.spark.sql.catalyst.plans.logical.EventTimeWatermark import org.apache.spark.sql.catalyst.types.DataTypeUtils.toAttributes import org.apache.spark.sql.execution.metric.SQLMetric -import org.apache.spark.sql.execution.streaming.operators.stateful.StatefulOperatorStateInfo -import org.apache.spark.sql.execution.streaming.operators.stateful.StatefulOpStateStoreCheckpointInfo +import org.apache.spark.sql.execution.streaming.operators.stateful.{StatefulOperatorStateInfo, StatefulOpStateStoreCheckpointInfo, WatermarkSupport} import org.apache.spark.sql.execution.streaming.operators.stateful.join.StreamingSymmetricHashJoinHelper._ -import org.apache.spark.sql.execution.streaming.state.{DropLastNFieldsStatePartitionKeyExtractor, KeyStateEncoderSpec, NoopStatePartitionKeyExtractor, NoPrefixKeyStateEncoderSpec, StatePartitionKeyExtractor, StateSchemaBroadcast, StateStore, StateStoreCheckpointInfo, StateStoreColFamilySchema, StateStoreConf, StateStoreErrors, StateStoreId, StateStoreMetrics, StateStoreProvider, StateStoreProviderId, SupportsFineGrainedReplay} -import org.apache.spark.sql.types.{BooleanType, LongType, StructField, StructType} +import org.apache.spark.sql.execution.streaming.state.{DropLastNFieldsStatePartitionKeyExtractor, KeyStateEncoderSpec, NoopStatePartitionKeyExtractor, NoPrefixKeyStateEncoderSpec, StatePartitionKeyExtractor, StateSchemaBroadcast, StateStore, StateStoreCheckpointInfo, StateStoreColFamilySchema, StateStoreConf, StateStoreErrors, StateStoreId, StateStoreMetrics, StateStoreProvider, StateStoreProviderId, SupportsFineGrainedReplay, TimestampAsPostfixKeyStateEncoderSpec, TimestampAsPrefixKeyStateEncoderSpec, TimestampKeyStateEncoder} +import org.apache.spark.sql.types.{BooleanType, DataType, LongType, NullType, StructField, StructType} import org.apache.spark.util.NextIterator +/** + * Base trait of the state manager for stream-stream symmetric hash join operator. + * + * This defines the basic APIs for the state manager, except the methods for eviction which are + * defined in separate traits - See [[SupportsEvictByCondition]] and [[SupportsEvictByTimestamp]]. + * + * Implementation classes are expected to inherit those traits as needed, depending on the eviction + * strategy they support. + */ +trait SymmetricHashJoinStateManager { + import SymmetricHashJoinStateManager._ + + /** Append a new value to the given key, with the flag of matched or not. */ + def append(key: UnsafeRow, value: UnsafeRow, matched: Boolean): Unit + + /** + * Retrieve all matched values from given key. This doesn't update the matched flag for the + * values being returned, hence should be only used if appropriate for the join type and the + * side. + */ + def get(key: UnsafeRow): Iterator[UnsafeRow] + + /** + * Retrieve all joined rows for the given key. The joined rows are generated with the provided + * generateJoinedRow function and filtered with the provided predicate. + * + * For excludeRowsAlreadyMatched = true, the method will only return the joined rows for the + * values which have not been marked as matched yet. The matched flag will be updated to true + * for the values being returned, if it is semantically required to do so. + * + * It is caller's responsibility to consume the whole iterator. + */ + def getJoinedRows( + key: UnsafeRow, + generateJoinedRow: InternalRow => JoinedRow, + predicate: JoinedRow => Boolean, + excludeRowsAlreadyMatched: Boolean = false): Iterator[JoinedRow] + + /** + * Provide all key-value pairs in the state manager. + * + * It is caller's responsibility to consume the whole iterator. + */ + def iterator: Iterator[KeyToValuePair] + + /** Commit all the changes to all the state stores */ + def commit(): Unit + + /** Abort any changes to the state stores if needed */ + def abortIfNeeded(): Unit + + /** Provide the metrics. */ + def metrics: StateStoreMetrics + + /** + * Get state store checkpoint information of the two state stores for this joiner, after + * they finished data processing. + */ + def getLatestCheckpointInfo(): JoinerStateStoreCkptInfo +} + +/** + * This trait is specific to help the old version of state manager implementation (v1-v3) to work + * with existing tests which look up the state store with key with index. + */ +trait SupportsIndexedKeys { + def getInternalRowOfKeyWithIndex(currentKey: UnsafeRow): InternalRow + + protected[streaming] def updateNumValuesTestOnly(key: UnsafeRow, numValues: Long): Unit +} + +/** + * This trait is for state manager implementations that support eviction by condition. + * This is for the state manager implementations which have to perform full scan + * for eviction. + */ +trait SupportsEvictByCondition { self: SymmetricHashJoinStateManager => + import SymmetricHashJoinStateManager._ + + /** Evict the state via condition on the key. Returns the number of values evicted. */ + def evictByKeyCondition(removalCondition: UnsafeRow => Boolean): Long + + /** + * Evict the state via condition on the key, and return the evicted key-value pairs. + * + * It is caller's responsibility to consume the whole iterator. + */ + def evictAndReturnByKeyCondition( + removalCondition: UnsafeRow => Boolean): Iterator[KeyToValuePair] + + /** Evict the state via condition on the value. Returns the number of values evicted. */ + def evictByValueCondition(removalCondition: UnsafeRow => Boolean): Long + + /** + * Evict the state via condition on the value, and return the evicted key-value pairs. + * + * It is caller's responsibility to consume the whole iterator. + */ + def evictAndReturnByValueCondition( + removalCondition: UnsafeRow => Boolean): Iterator[KeyToValuePair] +} + +/** + * This trait is for state manager implementations that support eviction by timestamp. This is for + * the state manager implementations which maintain the state with event time and can efficiently + * scan the keys with event time smaller than the given timestamp for eviction. + */ +trait SupportsEvictByTimestamp { self: SymmetricHashJoinStateManager => + import SymmetricHashJoinStateManager._ + + /** Evict the state by timestamp. Returns the number of values evicted. */ + def evictByTimestamp(endTimestamp: Long): Long + + /** + * Evict the state by timestamp and return the evicted key-value pairs. + * + * It is caller's responsibility to consume the whole iterator. + */ + def evictAndReturnByTimestamp(endTimestamp: Long): Iterator[KeyToValuePair] +} + +/** + * The version 4 of stream-stream join state manager implementation, which is designed to optimize + * the eviction with watermark. Previous versions require full scan to find the keys to evict, + * while this version only scans the keys with event time smaller than the watermark. + * + * In this implementation, we no longer build a logical array of values; instead, we store the + * (key, timestamp) -> values in the primary store, and maintain a secondary index of + * (timestamp, key) to scan the keys to evict for each watermark. To retrieve the values for a key, + * we perform prefix scan with the key to get all the (key, timestamp) -> values. + * + * This implementation leverages (virtual) column family, and uses features which are only + * available in RocksDB state store provider. Please make sure to set the state store provider to + * RocksDBStateStoreProvider. + * + * Refer to the [[KeyWithTsToValuesStore]] and [[TsWithKeyTypeStore]] for more details. + */ +class SymmetricHashJoinStateManagerV4( + joinSide: JoinSide, + inputValueAttributes: Seq[Attribute], + joinKeys: Seq[Expression], + stateInfo: Option[StatefulOperatorStateInfo], + storeConf: StateStoreConf, + hadoopConf: Configuration, + partitionId: Int, + keyToNumValuesStateStoreCkptId: Option[String], + keyWithIndexToValueStateStoreCkptId: Option[String], + stateFormatVersion: Int, + skippedNullValueCount: Option[SQLMetric] = None, + useStateStoreCoordinator: Boolean = true, + snapshotOptions: Option[SnapshotOptions] = None, + joinStoreGenerator: JoinStateManagerStoreGenerator) + extends SymmetricHashJoinStateManager with SupportsEvictByTimestamp with Logging { + + // TODO: [SPARK-55729] Once the new state manager is integrated to stream-stream join operator, + // we should support state data source to understand the state for state format version v4. + + import SymmetricHashJoinStateManager._ + + protected val keySchema = StructType( + joinKeys.zipWithIndex.map { case (k, i) => StructField(s"field$i", k.dataType, k.nullable) }) + protected val keyAttributes = toAttributes(keySchema) + private val eventTimeColIdxOpt = WatermarkSupport.findEventTimeColumnIndex( + inputValueAttributes, + // NOTE: This does not accept multiple event time columns. This is not the same with the + // operator which we offer the backward compatibility, but it involves too many layers to + // pass the information. The information is in SQLConf. + allowMultipleEventTimeColumns = false) + + private val random = new scala.util.Random(System.currentTimeMillis()) + private val bucketCountForNoEventTime = 1024 + private val extractEventTimeFn: UnsafeRow => Long = { row => + eventTimeColIdxOpt match { + case Some(idx) => + val attr = inputValueAttributes(idx) + + if (attr.dataType.isInstanceOf[StructType]) { + // NOTE: We assume this is window struct, as same as WatermarkSupport.watermarkExpression + row.getStruct(idx, 2).getLong(1) + } else { + row.getLong(idx) + } + + case _ => + // When event time column is not available, we will use random bucketing strategy to decide + // where the new value will be stored. There is a trade-off between the bucket size and the + // number of values in each bucket; we can tune the bucket size with the configuration if + // we figure out the magic number to not work well. + random.nextInt(bucketCountForNoEventTime) + } + } + + private val eventTimeColIdxOptInKey: Option[Int] = { + joinKeys.zipWithIndex.collectFirst { + case (ne: NamedExpression, index) + if ne.metadata.contains(EventTimeWatermark.delayKey) => index + } + } + + private val extractEventTimeFnFromKey: UnsafeRow => Option[Long] = { row => + eventTimeColIdxOptInKey.map { idx => + val attr = keyAttributes(idx) + if (attr.dataType.isInstanceOf[StructType]) { + // NOTE: We assume this is window struct, as same as WatermarkSupport.watermarkExpression + row.getStruct(idx, 2).getLong(1) + } else { + row.getLong(idx) + } + } + } + + private val dummySchema = StructType( + Seq(StructField("dummy", NullType, nullable = true)) + ) + + // TODO: [SPARK-55628] Below two fields need to be handled properly during integration with + // the operator. + private val stateStoreCkptId: Option[String] = None + private val handlerSnapshotOptions: Option[HandlerSnapshotOptions] = None + + private var stateStoreProvider: StateStoreProvider = _ + + // We will use the dummy schema for the default CF since we will register CF separately. + private val stateStore = getStateStore( + dummySchema, dummySchema, useVirtualColumnFamilies = true, + NoPrefixKeyStateEncoderSpec(dummySchema), useMultipleValuesPerKey = false + ) + + private def getStateStore( + keySchema: StructType, + valueSchema: StructType, + useVirtualColumnFamilies: Boolean, + keyStateEncoderSpec: KeyStateEncoderSpec, + useMultipleValuesPerKey: Boolean): StateStore = { + val storeName = StateStoreId.DEFAULT_STORE_NAME + val storeProviderId = StateStoreProviderId(stateInfo.get, partitionId, storeName) + val store = if (useStateStoreCoordinator) { + assert(handlerSnapshotOptions.isEmpty, "Should not use state store coordinator " + + "when reading state as data source.") + joinStoreGenerator.getStore( + storeProviderId, keySchema, valueSchema, keyStateEncoderSpec, + stateInfo.get.storeVersion, stateStoreCkptId, None, useVirtualColumnFamilies, + useMultipleValuesPerKey, storeConf, hadoopConf) + } else { + // This class will manage the state store provider by itself. + stateStoreProvider = StateStoreProvider.createAndInit( + storeProviderId, keySchema, valueSchema, keyStateEncoderSpec, + useColumnFamilies = useVirtualColumnFamilies, + storeConf, hadoopConf, useMultipleValuesPerKey = useMultipleValuesPerKey, + stateSchemaProvider = None) + if (handlerSnapshotOptions.isDefined) { + if (!stateStoreProvider.isInstanceOf[SupportsFineGrainedReplay]) { + throw StateStoreErrors.stateStoreProviderDoesNotSupportFineGrainedReplay( + stateStoreProvider.getClass.toString) + } + val opts = handlerSnapshotOptions.get + stateStoreProvider.asInstanceOf[SupportsFineGrainedReplay] + .replayStateFromSnapshot( + opts.snapshotVersion, + opts.endVersion, + readOnly = true, + opts.startStateStoreCkptId, + opts.endStateStoreCkptId) + } else { + stateStoreProvider.getStore(stateInfo.get.storeVersion, stateStoreCkptId) + } + } + logInfo(log"Loaded store ${MDC(STATE_STORE_ID, store.id)}") + store + } + + private val keyWithTsToValues = new KeyWithTsToValuesStore + + private val tsWithKey = new TsWithKeyTypeStore + + override def append(key: UnsafeRow, value: UnsafeRow, matched: Boolean): Unit = { + val eventTime = extractEventTimeFn(value) + // We always do blind merge for appending new value. + keyWithTsToValues.append(key, eventTime, value, matched) + tsWithKey.add(eventTime, key) + } + + override def getJoinedRows( + key: UnsafeRow, + generateJoinedRow: InternalRow => JoinedRow, + predicate: JoinedRow => Boolean, + excludeRowsAlreadyMatched: Boolean): Iterator[JoinedRow] = { + // TODO: [SPARK-55147] We could improve this method to get the scope of timestamp and scan keys + // more efficiently. For now, we just get all values for the key. + def getJoinedRowsFromTsAndValues( + ts: Long, + valuesAndMatched: Array[ValueAndMatchPair]): Iterator[JoinedRow] = { + new NextIterator[JoinedRow] { + private var currentIndex = 0 + + private var shouldUpdateValuesIntoStateStore = false + + override protected def getNext(): JoinedRow = { + var ret: JoinedRow = null + while (ret == null && currentIndex < valuesAndMatched.length) { + val vmp = valuesAndMatched(currentIndex) + + if (excludeRowsAlreadyMatched && vmp.matched) { + // Skip this one + } else { + val joinedRow = generateJoinedRow(vmp.value) + if (predicate(joinedRow)) { + if (!vmp.matched) { + // Update the array to contain the value having matched = true + valuesAndMatched(currentIndex) = vmp.copy(matched = true) + // Need to update matched flag + shouldUpdateValuesIntoStateStore = true + } + + ret = joinedRow + } else { + // skip this one + } + } + + currentIndex += 1 + } + + if (ret == null) { + assert(currentIndex == valuesAndMatched.length) + finished = true + null + } else { + ret + } + } + + override protected def close(): Unit = { + if (shouldUpdateValuesIntoStateStore) { + // Update back to the state store + val updatedValuesWithMatched = valuesAndMatched.map { vmp => + (vmp.value, vmp.matched) + }.toSeq + keyWithTsToValues.put(key, ts, updatedValuesWithMatched) + } + } + } + } + + val ret = extractEventTimeFnFromKey(key) match { + case Some(ts) => + val valuesAndMatchedIter = keyWithTsToValues.get(key, ts) + getJoinedRowsFromTsAndValues(ts, valuesAndMatchedIter.toArray) + + case _ => + keyWithTsToValues.getValues(key).flatMap { result => + val ts = result.timestamp + val valuesAndMatched = result.values.toArray + getJoinedRowsFromTsAndValues(ts, valuesAndMatched) + } + } + ret.filter(_ != null) + } + + /** + * NOTE: The entry provided by Iterator.next() will be reused. It is a caller's responsibility + * to copy it properly if caller needs to keep the reference after next() is called again. + */ + override def iterator: Iterator[KeyToValuePair] = { + val reusableKeyToValuePair = KeyToValuePair() + keyWithTsToValues.iterator().map { kv => + reusableKeyToValuePair.withNew(kv.key, kv.value, kv.matched) + } + } + + override def evictByTimestamp(endTimestamp: Long): Long = { + var removed = 0L + tsWithKey.scanEvictedKeys(endTimestamp).foreach { evicted => + val key = evicted.key + val timestamp = evicted.timestamp + val numValues = evicted.numValues + + // Remove from both primary and secondary stores + keyWithTsToValues.remove(key, timestamp) + tsWithKey.remove(key, timestamp) + + removed += numValues + } + removed + } + + override def evictAndReturnByTimestamp(endTimestamp: Long): Iterator[KeyToValuePair] = { + val reusableKeyToValuePair = KeyToValuePair() + + tsWithKey.scanEvictedKeys(endTimestamp).flatMap { evicted => + val key = evicted.key + val timestamp = evicted.timestamp + val values = keyWithTsToValues.get(key, timestamp) + + // Remove from both primary and secondary stores + keyWithTsToValues.remove(key, timestamp) + tsWithKey.remove(key, timestamp) + + values.map { value => + reusableKeyToValuePair.withNew(key, value) + } + } + } + + override def commit(): Unit = { + stateStore.commit() + logDebug("Committed, metrics = " + stateStore.metrics) + } + + override def abortIfNeeded(): Unit = { + if (!stateStore.hasCommitted) { + logInfo(log"Aborted store ${MDC(STATE_STORE_ID, stateStore.id)}") + stateStore.abort() + } + // If this class manages a state store provider by itself, it should take care of closing + // provider instance as well. + if (stateStoreProvider != null) { + stateStoreProvider.close() + } + } + + // Clean up any state store resources if necessary at the end of the task + Option(TaskContext.get()).foreach { _.addTaskCompletionListener[Unit] { _ => abortIfNeeded() } } + + class GetValuesResult(var timestamp: Long = -1, var values: Seq[ValueAndMatchPair] = Seq.empty) { + def withNew(newTimestamp: Long, newValues: Seq[ValueAndMatchPair]): GetValuesResult = { + this.timestamp = newTimestamp + this.values = newValues + this + } + } + + /** + * The primary store to store the key-value pairs. + * + * The state format of the primary store is following: + * [key][timestamp (event time)] -> [(value, matched), (value, matched), ...] + * + * The values are bucketed by event time to facilitate efficient eviction by watermark; the + * secondary index will provide the way to scan the key + timestamp pairs for the eviction, and + * it will be easy to perform retrieval/removal of the values based on key + timestamp pairs. + * There is no case where we evict only part of the values for the same key + timestamp. + * + * The matched flag is used to indicate whether the value has been matched with any row from the + * other side. + */ + private class KeyWithTsToValuesStore { + private val valueRowConverter = StreamingSymmetricHashJoinValueRowConverter.create( + inputValueAttributes, stateFormatVersion = 4) + + // Set up virtual column family name in the store if it is being used + private val colFamilyName = getStateStoreName(joinSide, KeyWithTsToValuesType) + + private val keySchemaWithTimestamp = TimestampKeyStateEncoder.keySchemaWithTimestamp(keySchema) + private val detachTimestampProjection: UnsafeProjection = + TimestampKeyStateEncoder.getDetachTimestampProjection(keySchemaWithTimestamp) + private val attachTimestampProjection: UnsafeProjection = + TimestampKeyStateEncoder.getAttachTimestampProjection(keySchema) + + // Create the specific column family in the store for this join side's KeyWithIndexToValueStore + stateStore.createColFamilyIfAbsent( + colFamilyName, + keySchema, + valueRowConverter.valueAttributes.toStructType, + TimestampAsPostfixKeyStateEncoderSpec(keySchemaWithTimestamp), + useMultipleValuesPerKey = true + ) + + private def createKeyRow(key: UnsafeRow, timestamp: Long): UnsafeRow = { + TimestampKeyStateEncoder.attachTimestamp( + attachTimestampProjection, keySchemaWithTimestamp, key, timestamp) + } + + def append(key: UnsafeRow, timestamp: Long, value: UnsafeRow, matched: Boolean): Unit = { + val valueWithMatched = valueRowConverter.convertToValueRow(value, matched) + stateStore.merge(createKeyRow(key, timestamp), valueWithMatched, colFamilyName) + } + + def put( + key: UnsafeRow, + timestamp: Long, + valuesWithMatched: Seq[(UnsafeRow, Boolean)]): Unit = { + // copy() is required because convertToValueRow reuses its internal UnsafeProjection output + // TODO: [SPARK-55732] StateStore.putList should allow iterator to be passed in, so that we + // don't need to materialize the array and copy the values here. + val valuesToPut = valuesWithMatched.map { case (value, matched) => + valueRowConverter.convertToValueRow(value, matched).copy() + }.toArray + stateStore.putList(createKeyRow(key, timestamp), valuesToPut, colFamilyName) + } + + def get(key: UnsafeRow, timestamp: Long): Iterator[ValueAndMatchPair] = { + stateStore.valuesIterator(createKeyRow(key, timestamp), colFamilyName).map { valueRow => + valueRowConverter.convertValue(valueRow) + } + } + + // NOTE: We do not have a case where we only remove a part of values. Even if that is needed + // we handle it via put() with writing a new array. + def remove(key: UnsafeRow, timestamp: Long): Unit = { + stateStore.remove(createKeyRow(key, timestamp), colFamilyName) + } + + // NOTE: This assumes we consume the whole iterator to trigger completion. + def getValues(key: UnsafeRow): Iterator[GetValuesResult] = { + val reusableGetValuesResult = new GetValuesResult() + + new NextIterator[GetValuesResult] { + private val iter = stateStore.prefixScanWithMultiValues(key, colFamilyName) + + private var currentTs = -1L + private val valueAndMatchPairs = scala.collection.mutable.ArrayBuffer[ValueAndMatchPair]() + + @tailrec + override protected def getNext(): GetValuesResult = { + if (iter.hasNext) { + val unsafeRowPair = iter.next() + + val ts = TimestampKeyStateEncoder.extractTimestamp(unsafeRowPair.key) + + if (currentTs == -1L) { + // First time + currentTs = ts + } + + if (currentTs != ts) { + assert(valueAndMatchPairs.nonEmpty, + "timestamp has changed but no values collected from previous timestamp! " + + s"This should not happen. currentTs: $currentTs, new ts: $ts") + + // Return previous batch + val result = reusableGetValuesResult.withNew( + currentTs, valueAndMatchPairs.toSeq) + + // Reset for new timestamp + currentTs = ts + valueAndMatchPairs.clear() + + // Add current value + val value = valueRowConverter.convertValue(unsafeRowPair.value) + valueAndMatchPairs += value + result + } else { + // Same timestamp, accumulate values + val value = valueRowConverter.convertValue(unsafeRowPair.value) + valueAndMatchPairs += value + + // Continue to next + getNext() + } + } else { + if (currentTs != -1L) { + assert(valueAndMatchPairs.nonEmpty) + + // Return last batch + val result = reusableGetValuesResult.withNew( + currentTs, valueAndMatchPairs.toSeq) + + // Mark as finished + currentTs = -1L + valueAndMatchPairs.clear() + result + } else { + finished = true + null + } + } + } + + override protected def close(): Unit = iter.close() + } + } + + def iterator(): Iterator[KeyAndTsToValuePair] = { + val iter = stateStore.iteratorWithMultiValues(colFamilyName) + val reusableKeyAndTsToValuePair = KeyAndTsToValuePair() + iter.map { kv => + val keyRow = detachTimestampProjection(kv.key) + val ts = TimestampKeyStateEncoder.extractTimestamp(kv.key) + val value = valueRowConverter.convertValue(kv.value) + + reusableKeyAndTsToValuePair.withNew(keyRow, ts, value) + } + } + } + + /** + * The secondary index for efficient state removal with watermark. + * + * The state format of the secondary index is following: + * [timestamp (adjusted for ordering, 8 bytes)][key] -> [list of empty values] + * + * The value part is used to track the number of values for the same (key, timestamp) in the + * primary store, so that we can track the number of values being removed for each eviction and + * update metrics accordingly. Alternatively, we can also maintain an integer count in the value + * part, but we found blind merge and count later to be more efficient than read-modify-write. + */ + private class TsWithKeyTypeStore { + private val valueStructType = StructType(Array(StructField("__dummy__", NullType))) + private val EMPTY_ROW = + UnsafeProjection.create(Array[DataType](NullType)).apply(InternalRow.apply(null)) + + // Set up virtual column family name in the store if it is being used + private val colFamilyName = getStateStoreName(joinSide, TsWithKeyType) + + private val keySchemaWithTimestamp = TimestampKeyStateEncoder.keySchemaWithTimestamp(keySchema) + private val detachTimestampProjection: UnsafeProjection = + TimestampKeyStateEncoder.getDetachTimestampProjection(keySchemaWithTimestamp) + private val attachTimestampProjection: UnsafeProjection = + TimestampKeyStateEncoder.getAttachTimestampProjection(keySchema) + + // Create the specific column family in the store for this join side's KeyWithIndexToValueStore + stateStore.createColFamilyIfAbsent( + colFamilyName, + keySchema, + valueStructType, + TimestampAsPrefixKeyStateEncoderSpec(keySchemaWithTimestamp), + useMultipleValuesPerKey = true + ) + + private def createKeyRow(key: UnsafeRow, timestamp: Long): UnsafeRow = { + TimestampKeyStateEncoder.attachTimestamp( + attachTimestampProjection, keySchemaWithTimestamp, key, timestamp) + } + + def add(timestamp: Long, key: UnsafeRow): Unit = { + stateStore.merge(createKeyRow(key, timestamp), EMPTY_ROW, colFamilyName) + } + + def remove(key: UnsafeRow, timestamp: Long): Unit = { + stateStore.remove(createKeyRow(key, timestamp), colFamilyName) + } + + case class EvictedKeysResult(key: UnsafeRow, timestamp: Long, numValues: Int) + + // NOTE: This assumes we consume the whole iterator to trigger completion. + def scanEvictedKeys(endTimestamp: Long): Iterator[EvictedKeysResult] = { + val evictIterator = stateStore.iteratorWithMultiValues(colFamilyName) + new NextIterator[EvictedKeysResult]() { + var currentKeyRow: UnsafeRow = null + var currentEventTime: Long = -1L + var count: Int = 0 + var isBeyondUpperBound: Boolean = false + + override protected def getNext(): EvictedKeysResult = { + var ret: EvictedKeysResult = null + while (evictIterator.hasNext && ret == null && !isBeyondUpperBound) { + val kv = evictIterator.next() + val keyRow = detachTimestampProjection(kv.key) + val ts = TimestampKeyStateEncoder.extractTimestamp(kv.key) + + if (keyRow == currentKeyRow && ts == currentEventTime) { + // new value with same (key, ts) + count += 1 + } else if (ts > endTimestamp) { + // we found the timestamp beyond the range - we shouldn't continue further + isBeyondUpperBound = true + + // We don't need to construct the last (key, ts) into EvictedKeysResult - the code + // after loop will handle that if there is leftover. That said, we do not reset the + // current (key, ts) info here. + } else if (currentKeyRow == null && currentEventTime == -1L) { + // first value to process + currentKeyRow = keyRow.copy() + currentEventTime = ts + count = 1 + } else { + // construct the last (key, ts) into EvictedKeysResult + ret = EvictedKeysResult(currentKeyRow, currentEventTime, count) + + // register the next (key, ts) to process + currentKeyRow = keyRow.copy() + currentEventTime = ts + count = 1 + } + } + + if (ret != null) { + ret + } else if (count > 0) { + // there is a final leftover (key, ts) to return + ret = EvictedKeysResult(currentKeyRow, currentEventTime, count) + + // we shouldn't continue further + currentKeyRow = null + currentEventTime = -1L + count = 0 + + ret + } else { + finished = true + null + } + } + + override protected def close(): Unit = { + evictIterator.close() + } + } + } + } + + override def get(key: UnsafeRow): Iterator[UnsafeRow] = { + keyWithTsToValues.getValues(key).flatMap { result => + result.values.map(_.value) + } + } + + def metrics: StateStoreMetrics = stateStore.metrics + + def getLatestCheckpointInfo(): JoinerStateStoreCkptInfo = { + val keyToNumValuesCkptInfo = stateStore.getStateStoreCheckpointInfo() + val keyWithIndexToValueCkptInfo = stateStore.getStateStoreCheckpointInfo() + + assert(keyToNumValuesCkptInfo == keyWithIndexToValueCkptInfo) + + JoinerStateStoreCkptInfo(keyToNumValuesCkptInfo, keyWithIndexToValueCkptInfo) + } +} + /** * Helper class to manage state required by a single side of * [[org.apache.spark.sql.execution.streaming.StreamingSymmetricHashJoinExec]]. @@ -84,7 +804,7 @@ import org.apache.spark.util.NextIterator * by overwriting with the value of (key, maxIndex), and removing [(key, maxIndex), * decrement corresponding num values in KeyToNumValuesStore */ -abstract class SymmetricHashJoinStateManager( +abstract class SymmetricHashJoinStateManagerBase( joinSide: JoinSide, inputValueAttributes: Seq[Attribute], joinKeys: Seq[Expression], @@ -98,17 +818,22 @@ abstract class SymmetricHashJoinStateManager( skippedNullValueCount: Option[SQLMetric] = None, useStateStoreCoordinator: Boolean = true, snapshotOptions: Option[SnapshotOptions] = None, - joinStoreGenerator: JoinStateManagerStoreGenerator) extends Logging { + joinStoreGenerator: JoinStateManagerStoreGenerator) + extends SymmetricHashJoinStateManager + with SupportsEvictByCondition + with SupportsIndexedKeys + with Logging { + import SymmetricHashJoinStateManager._ - private[streaming] val keySchema = StructType( + protected val keySchema = StructType( joinKeys.zipWithIndex.map { case (k, i) => StructField(s"field$i", k.dataType, k.nullable) }) protected val keyAttributes = toAttributes(keySchema) - private[streaming] val keyToNumValues = new KeyToNumValuesStore( + protected val keyToNumValues = new KeyToNumValuesStore( stateFormatVersion, snapshotOptions.map(_.getKeyToNumValuesHandlerOpts())) - private[streaming] val keyWithIndexToValue = new KeyWithIndexToValueStore( + protected val keyWithIndexToValue = new KeyWithIndexToValueStore( stateFormatVersion, snapshotOptions.map(_.getKeyWithIndexToValueHandlerOpts())) @@ -161,6 +886,25 @@ abstract class SymmetricHashJoinStateManager( }.filter(_ != null) } + /** Remove using a predicate on keys. */ + override def evictByKeyCondition(removalCondition: UnsafeRow => Boolean): Long = { + var numRemoved = 0L + keyToNumValues.iterator.foreach { keyAndNumValues => + val key = keyAndNumValues.key + if (removalCondition(key)) { + val numValue = keyAndNumValues.numValue + + (0L until numValue).foreach { idx => + keyWithIndexToValue.remove(key, idx) + } + + numRemoved += numValue + keyToNumValues.remove(key) + } + } + numRemoved + } + /** * Remove using a predicate on keys. * @@ -170,7 +914,8 @@ abstract class SymmetricHashJoinStateManager( * This implies the iterator must be consumed fully without any other operations on this manager * or the underlying store being interleaved. */ - def removeByKeyCondition(removalCondition: UnsafeRow => Boolean): Iterator[KeyToValuePair] = { + override def evictAndReturnByKeyCondition( + removalCondition: UnsafeRow => Boolean): Iterator[KeyToValuePair] = { new NextIterator[KeyToValuePair] { private val allKeyToNumValues = keyToNumValues.iterator @@ -268,6 +1013,14 @@ abstract class SymmetricHashJoinStateManager( } } + override def evictByValueCondition(removalCondition: UnsafeRow => Boolean): Long = { + var numRemoved = 0L + evictAndReturnByValueCondition(removalCondition).foreach { _ => + numRemoved += 1 + } + numRemoved + } + /** * Remove using a predicate on values. * @@ -278,7 +1031,8 @@ abstract class SymmetricHashJoinStateManager( * This implies the iterator must be consumed fully without any other operations on this manager * or the underlying store being interleaved. */ - def removeByValueCondition(removalCondition: UnsafeRow => Boolean): Iterator[KeyToValuePair] = { + override def evictAndReturnByValueCondition( + removalCondition: UnsafeRow => Boolean): Iterator[KeyToValuePair] = { new NextIterator[KeyToValuePair] { // Reuse this object to avoid creation+GC overhead. @@ -447,7 +1201,7 @@ abstract class SymmetricHashJoinStateManager( * NOTE: this function is only intended for use in unit tests * to simulate null values. */ - private[streaming] def updateNumValuesTestOnly(key: UnsafeRow, numValues: Long): Unit = { + protected[streaming] def updateNumValuesTestOnly(key: UnsafeRow, numValues: Long): Unit = { keyToNumValues.put(key, numValues) } @@ -510,7 +1264,7 @@ abstract class SymmetricHashJoinStateManager( joinStoreGenerator.getStore( storeProviderId, keySchema, valueSchema, NoPrefixKeyStateEncoderSpec(keySchema), stateInfo.get.storeVersion, stateStoreCkptId, None, useVirtualColumnFamilies, - storeConf, hadoopConf) + useMultipleValuesPerKey = false, storeConf, hadoopConf) } else { // This class will manage the state store provider by itself. stateStoreProvider = StateStoreProvider.createAndInit( @@ -551,7 +1305,6 @@ abstract class SymmetricHashJoinStateManager( } } - /** A wrapper around a [[StateStore]] that stores [key -> number of values]. */ protected class KeyToNumValuesStore( val stateFormatVersion: Int, @@ -648,78 +1401,6 @@ SnapshotOptions } } - private trait KeyWithIndexToValueRowConverter { - /** Defines the schema of the value row (the value side of K-V in state store). */ - def valueAttributes: Seq[Attribute] - - /** - * Convert the value row to (actual value, match) pair. - * - * NOTE: implementations should ensure the result row is NOT reused during execution, so - * that caller can safely read the value in any time. - */ - def convertValue(value: UnsafeRow): ValueAndMatchPair - - /** - * Build the value row from (actual value, match) pair. This is expected to be called just - * before storing to the state store. - * - * NOTE: depending on the implementation, the result row "may" be reused during execution - * (to avoid initialization of object), so the caller should ensure that the logic doesn't - * affect by such behavior. Call copy() against the result row if needed. - */ - def convertToValueRow(value: UnsafeRow, matched: Boolean): UnsafeRow - } - - private object KeyWithIndexToValueRowConverter { - def create(version: Int): KeyWithIndexToValueRowConverter = version match { - case 1 => new KeyWithIndexToValueRowConverterFormatV1() - case 2 | 3 => new KeyWithIndexToValueRowConverterFormatV2() - case _ => throw new IllegalArgumentException("Incorrect state format version! " + - s"version $version") - } - } - - private class KeyWithIndexToValueRowConverterFormatV1 extends KeyWithIndexToValueRowConverter { - override val valueAttributes: Seq[Attribute] = inputValueAttributes - - override def convertValue(value: UnsafeRow): ValueAndMatchPair = { - if (value != null) ValueAndMatchPair(value, false) else null - } - - override def convertToValueRow(value: UnsafeRow, matched: Boolean): UnsafeRow = value - } - - private class KeyWithIndexToValueRowConverterFormatV2 extends KeyWithIndexToValueRowConverter { - private val valueWithMatchedExprs = inputValueAttributes :+ Literal(true) - private val indexOrdinalInValueWithMatchedRow = inputValueAttributes.size - - private val valueWithMatchedRowGenerator = UnsafeProjection.create(valueWithMatchedExprs, - inputValueAttributes) - - override val valueAttributes: Seq[Attribute] = inputValueAttributes :+ - AttributeReference("matched", BooleanType)() - - // Projection to generate key row from (value + matched) row - private val valueRowGenerator = UnsafeProjection.create( - inputValueAttributes, valueAttributes) - - override def convertValue(value: UnsafeRow): ValueAndMatchPair = { - if (value != null) { - ValueAndMatchPair(valueRowGenerator(value).copy(), - value.getBoolean(indexOrdinalInValueWithMatchedRow)) - } else { - null - } - } - - override def convertToValueRow(value: UnsafeRow, matched: Boolean): UnsafeRow = { - val row = valueWithMatchedRowGenerator(value) - row.setBoolean(indexOrdinalInValueWithMatchedRow, matched) - row - } - } - /** * A wrapper around a [[StateStore]] that stores the mapping; the mapping depends on the * state format version - please refer implementations of [[KeyWithIndexToValueRowConverter]]. @@ -742,7 +1423,8 @@ SnapshotOptions private val keyRowGenerator = UnsafeProjection.create( keyAttributes, keyAttributes :+ AttributeReference("index", LongType)()) - private val valueRowConverter = KeyWithIndexToValueRowConverter.create(stateFormatVersion) + private val valueRowConverter = StreamingSymmetricHashJoinValueRowConverter + .create(inputValueAttributes, stateFormatVersion) protected val stateStore = getStateStore(keyWithIndexSchema, valueRowConverter.valueAttributes.toStructType, useVirtualColumnFamilies) @@ -869,11 +1551,12 @@ class SymmetricHashJoinStateManagerV1( skippedNullValueCount: Option[SQLMetric] = None, useStateStoreCoordinator: Boolean = true, snapshotOptions: Option[SnapshotOptions] = None, - joinStoreGenerator: JoinStateManagerStoreGenerator) extends SymmetricHashJoinStateManager( - joinSide, inputValueAttributes, joinKeys, stateInfo, storeConf, hadoopConf, - partitionId, keyToNumValuesStateStoreCkptId, keyWithIndexToValueStateStoreCkptId, - stateFormatVersion, skippedNullValueCount, useStateStoreCoordinator, snapshotOptions, - joinStoreGenerator) { + joinStoreGenerator: JoinStateManagerStoreGenerator) + extends SymmetricHashJoinStateManagerBase( + joinSide, inputValueAttributes, joinKeys, stateInfo, storeConf, hadoopConf, + partitionId, keyToNumValuesStateStoreCkptId, keyWithIndexToValueStateStoreCkptId, + stateFormatVersion, skippedNullValueCount, useStateStoreCoordinator, snapshotOptions, + joinStoreGenerator) { /** Commit all the changes to all the state stores */ override def commit(): Unit = { @@ -948,11 +1631,12 @@ class SymmetricHashJoinStateManagerV2( skippedNullValueCount: Option[SQLMetric] = None, useStateStoreCoordinator: Boolean = true, snapshotOptions: Option[SnapshotOptions] = None, - joinStoreGenerator: JoinStateManagerStoreGenerator) extends SymmetricHashJoinStateManager( - joinSide, inputValueAttributes, joinKeys, stateInfo, storeConf, hadoopConf, - partitionId, keyToNumValuesStateStoreCkptId, keyWithIndexToValueStateStoreCkptId, - stateFormatVersion, skippedNullValueCount, useStateStoreCoordinator, snapshotOptions, - joinStoreGenerator) { + joinStoreGenerator: JoinStateManagerStoreGenerator) + extends SymmetricHashJoinStateManagerBase( + joinSide, inputValueAttributes, joinKeys, stateInfo, storeConf, hadoopConf, + partitionId, keyToNumValuesStateStoreCkptId, keyWithIndexToValueStateStoreCkptId, + stateFormatVersion, skippedNullValueCount, useStateStoreCoordinator, snapshotOptions, + joinStoreGenerator) { /** Commit all the changes to the state store */ override def commit(): Unit = { @@ -1001,6 +1685,7 @@ class JoinStateManagerStoreGenerator() extends Logging { * Creates the state store used for join operations, or returns the existing instance * if it has been previously created and virtual column families are enabled. */ + // scalastyle:off argcount def getStore( storeProviderId: StateStoreProviderId, keySchema: StructType, @@ -1010,6 +1695,7 @@ class JoinStateManagerStoreGenerator() extends Logging { stateStoreCkptId: Option[String], stateSchemaBroadcast: Option[StateSchemaBroadcast], useColumnFamilies: Boolean, + useMultipleValuesPerKey: Boolean, storeConf: StateStoreConf, hadoopConf: Configuration): StateStore = { if (useColumnFamilies) { @@ -1019,7 +1705,7 @@ class JoinStateManagerStoreGenerator() extends Logging { StateStore.get( storeProviderId, keySchema, valueSchema, keyStateEncoderSpec, version, stateStoreCkptId, stateSchemaBroadcast, useColumnFamilies = useColumnFamilies, - storeConf, hadoopConf + storeConf, hadoopConf, useMultipleValuesPerKey = useMultipleValuesPerKey ) ) } @@ -1029,14 +1715,15 @@ class JoinStateManagerStoreGenerator() extends Logging { StateStore.get( storeProviderId, keySchema, valueSchema, keyStateEncoderSpec, version, stateStoreCkptId, stateSchemaBroadcast, useColumnFamilies = useColumnFamilies, - storeConf, hadoopConf + storeConf, hadoopConf, useMultipleValuesPerKey = useMultipleValuesPerKey ) } } + // scalastyle:on } object SymmetricHashJoinStateManager { - val supportedVersions = Seq(1, 2, 3) + val supportedVersions = Seq(1, 2, 3, 4) val legacyVersion = 1 // scalastyle:off argcount @@ -1056,7 +1743,14 @@ object SymmetricHashJoinStateManager { useStateStoreCoordinator: Boolean = true, snapshotOptions: Option[SnapshotOptions] = None, joinStoreGenerator: JoinStateManagerStoreGenerator): SymmetricHashJoinStateManager = { - if (stateFormatVersion == 3) { + if (stateFormatVersion == 4) { + new SymmetricHashJoinStateManagerV4( + joinSide, inputValueAttributes, joinKeys, stateInfo, storeConf, hadoopConf, + partitionId, keyToNumValuesStateStoreCkptId, keyWithIndexToValueStateStoreCkptId, + stateFormatVersion, skippedNullValueCount, useStateStoreCoordinator, snapshotOptions, + joinStoreGenerator + ) + } else if (stateFormatVersion == 3) { new SymmetricHashJoinStateManagerV2( joinSide, inputValueAttributes, joinKeys, stateInfo, storeConf, hadoopConf, partitionId, keyToNumValuesStateStoreCkptId, keyWithIndexToValueStateStoreCkptId, @@ -1254,7 +1948,7 @@ object SymmetricHashJoinStateManager { } } - private[streaming] sealed trait StateStoreType + private[sql] sealed trait StateStoreType private[sql] case object KeyToNumValuesType extends StateStoreType { override def toString(): String = "keyToNumValues" @@ -1264,7 +1958,15 @@ object SymmetricHashJoinStateManager { override def toString(): String = "keyWithIndexToValue" } - private[streaming] def getStateStoreName( + private[sql] case object KeyWithTsToValuesType extends StateStoreType { + override def toString(): String = "keyWithTsToValues" + } + + private[sql] case object TsWithKeyType extends StateStoreType { + override def toString(): String = "tsWithKey" + } + + private[join] def getStateStoreName( joinSide: JoinSide, storeType: StateStoreType): String = { s"$joinSide-$storeType" } @@ -1277,7 +1979,9 @@ object SymmetricHashJoinStateManager { storeName == getStateStoreName(RightSide, KeyWithIndexToValueType)) { KeyWithIndexToValueType } else { - throw new IllegalArgumentException(s"Unknown join store name: $storeName") + // TODO: [SPARK-55628] Add support of KeyWithTsToValuesType and TsWithKeyType during + // integration. + throw new IllegalArgumentException(s"Unsupported join store name: $storeName") } } @@ -1289,15 +1993,19 @@ object SymmetricHashJoinStateManager { colFamilyName: String, stateKeySchema: StructType, stateFormatVersion: Int): StatePartitionKeyExtractor = { - assert(stateFormatVersion <= 3, "State format version must be less than or equal to 3") - val name = if (stateFormatVersion == 3) colFamilyName else storeName + assert(stateFormatVersion <= 4, "State format version must be less than or equal to 4") + val name = if (stateFormatVersion >= 3) colFamilyName else storeName if (getStoreType(name) == KeyWithIndexToValueType) { // For KeyWithIndex, the index is added to the join (i.e. partition) key. // Drop the last field (index) to get the partition key new DropLastNFieldsStatePartitionKeyExtractor(stateKeySchema, numLastColsToDrop = 1) - } else { + } else if (getStoreType(name) == KeyToNumValuesType) { // State key is the partition key new NoopStatePartitionKeyExtractor(stateKeySchema) + } else { + // TODO: [SPARK-55628] Add support of KeyWithTsToValuesType and TsWithKeyType during + // integration. + throw new IllegalArgumentException(s"Unsupported join store name: $storeName") } } @@ -1331,6 +2039,39 @@ object SymmetricHashJoinStateManager { this } } + + /** + * Helper class for representing data (key, timestamp) to (value, matched). + * Designed for object reuse. + */ + case class KeyAndTsToValuePair( + var key: UnsafeRow = null, + var timestamp: Long = -1L, + var value: UnsafeRow = null, + var matched: Boolean = false) { + def withNew( + newKey: UnsafeRow, + newTimestamp: Long, + newValue: UnsafeRow, + newMatched: Boolean): this.type = { + this.key = newKey + this.timestamp = newTimestamp + this.value = newValue + this.matched = newMatched + this + } + + def withNew( + newKey: UnsafeRow, + newTimestamp: Long, + newValue: ValueAndMatchPair): this.type = { + this.key = newKey + this.timestamp = newTimestamp + this.value = newValue.value + this.matched = newValue.matched + this + } + } } /** diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/statefulOperators.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/statefulOperators.scala index 6206e68326189..3e01a6e55d7b2 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/statefulOperators.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/operators/stateful/statefulOperators.scala @@ -669,6 +669,7 @@ object WatermarkSupport { val eventTimeColsSet = eventTimeCols.map(_.exprId).toSet if (eventTimeColsSet.size > 1) { throw new AnalysisException( + // TODO: [SPARK-55731] Assign error class for _LEGACY_ERROR_TEMP_3077 errorClass = "_LEGACY_ERROR_TEMP_3077", messageParameters = Map("eventTimeCols" -> eventTimeCols.mkString("(", ",", ")"))) } @@ -684,6 +685,43 @@ object WatermarkSupport { // pick the first element if exists eventTimeCols.headOption } + + /** + * Find the index of the column which is marked as "event time" column. + * + * If there are multiple event time columns in given column list, the behavior depends on the + * parameter `allowMultipleEventTimeColumns`. If it's set to true, the first occurred column will + * be returned. If not, this method will throw an AnalysisException as it is not allowed to have + * multiple event time columns. + */ + def findEventTimeColumnIndex( + attrs: Seq[Attribute], + allowMultipleEventTimeColumns: Boolean): Option[Int] = { + val eventTimeCols = attrs.zipWithIndex + .filter(_._1.metadata.contains(EventTimeWatermark.delayKey)) + if (!allowMultipleEventTimeColumns) { + // There is a case projection leads the same column (same exprId) to appear more than one + // time. Allowing them does not hurt the correctness of state row eviction, hence let's start + // with allowing them. + val eventTimeColsSet = eventTimeCols.map(_._1.exprId).toSet + if (eventTimeColsSet.size > 1) { + throw new AnalysisException( + // TODO: [SPARK-55731] Assign error class for _LEGACY_ERROR_TEMP_3077 + errorClass = "_LEGACY_ERROR_TEMP_3077", + messageParameters = Map("eventTimeCols" -> eventTimeCols.mkString("(", ",", ")"))) + } + + // With above check, even there are multiple columns in eventTimeCols, all columns must be + // the same. + } else { + // This is for compatibility with previous behavior - we allow multiple distinct event time + // columns and pick up the first occurrence. This is incorrect if non-first occurrence is + // not smaller than the first one, but allow this as "escape hatch" in case we break the + // existing query. + } + // pick the first element if exists + eventTimeCols.headOption.map(_._2) + } } /** diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/state/SymmetricHashJoinStateManagerSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/state/SymmetricHashJoinStateManagerSuite.scala index 2e46202b3b0ba..fd601394f12d8 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/state/SymmetricHashJoinStateManagerSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/state/SymmetricHashJoinStateManagerSuite.scala @@ -17,54 +17,256 @@ package org.apache.spark.sql.execution.streaming.state +import java.io.File import java.sql.Timestamp import java.util.UUID import org.apache.hadoop.conf.Configuration import org.scalatest.BeforeAndAfter -import org.scalatest.PrivateMethodTester import org.apache.spark.sql.SparkSession -import org.apache.spark.sql.catalyst.expressions.{Attribute, BoundReference, Expression, GenericInternalRow, LessThanOrEqual, Literal, UnsafeProjection, UnsafeRow} +import org.apache.spark.sql.catalyst.expressions.{Attribute, AttributeReference, BoundReference, Expression, GenericInternalRow, JoinedRow, LessThanOrEqual, Literal, UnsafeProjection, UnsafeRow} import org.apache.spark.sql.catalyst.expressions.codegen.GeneratePredicate import org.apache.spark.sql.catalyst.plans.logical.EventTimeWatermark import org.apache.spark.sql.catalyst.types.DataTypeUtils.toAttributes import org.apache.spark.sql.execution.metric.SQLMetric -import org.apache.spark.sql.execution.streaming.operators.stateful.{StatefulOperatorStateInfo, StatefulOperatorsUtils, StatePartitionKeyExtractorFactory} -import org.apache.spark.sql.execution.streaming.operators.stateful.join.{JoinStateManagerStoreGenerator, SymmetricHashJoinStateManager} +import org.apache.spark.sql.execution.streaming.operators.stateful.StatefulOperatorStateInfo +import org.apache.spark.sql.execution.streaming.operators.stateful.join.{JoinStateManagerStoreGenerator, SupportsEvictByCondition, SupportsEvictByTimestamp, SupportsIndexedKeys, SymmetricHashJoinStateManager} import org.apache.spark.sql.execution.streaming.operators.stateful.join.StreamingSymmetricHashJoinHelper.LeftSide +import org.apache.spark.sql.execution.streaming.operators.stateful.join.SymmetricHashJoinStateManager.KeyToValuePair import org.apache.spark.sql.internal.SQLConf import org.apache.spark.sql.streaming.StreamTest import org.apache.spark.sql.types._ import org.apache.spark.unsafe.types.UTF8String -class SymmetricHashJoinStateManagerSuite extends StreamTest with BeforeAndAfter - with PrivateMethodTester { - +abstract class SymmetricHashJoinStateManagerBaseSuite extends StreamTest with BeforeAndAfter { before { SparkSession.setActiveSession(spark) // set this before force initializing 'joinExec' spark.streams.stateStoreCoordinator // initialize the lazy coordinator } - SymmetricHashJoinStateManager.supportedVersions.foreach { version => - test(s"StreamingJoinStateManager V${version} - all operations") { - testAllOperations(version) + protected def inputValueAttributes: Seq[AttributeReference] + protected def inputValueAttributesWithWatermark: AttributeReference + protected def joinKeyExpressions: Seq[Expression] + + private def inputValueGen = UnsafeProjection.create(inputValueAttributes.map(_.dataType).toArray) + private def joinKeyGen = UnsafeProjection.create(joinKeyExpressions.map(_.dataType).toArray) + + protected def toInputValue(key: Int, value: Int): UnsafeRow = { + inputValueGen.apply(new GenericInternalRow(Array[Any](key, value))) + } + + protected def toJoinKeyRow(key: Int): UnsafeRow = { + joinKeyGen.apply(new GenericInternalRow(Array[Any](false, key, 10.0))) + } + + protected def toValueInt(inputValueRow: UnsafeRow): Int = inputValueRow.getInt(1) + + protected def append(key: Int, value: Int) + (implicit manager: SymmetricHashJoinStateManager): Unit = { + // we only put matched = false for simplicity - StreamingJoinSuite will test the functionality + manager.append(toJoinKeyRow(key), toInputValue(key, value), matched = false) + } + + protected def appendAndTest(key: Int, values: Int*) + (implicit manager: SymmetricHashJoinStateManager): Unit = { + values.foreach { value => append(key, value)} + require(get(key) === values) + } + + protected def getNumValues(key: Int) + (implicit manager: SymmetricHashJoinStateManager): Int = { + manager.get(toJoinKeyRow(key)).size + } + + protected def get(key: Int)(implicit manager: SymmetricHashJoinStateManager): Seq[Int] = { + manager.get(toJoinKeyRow(key)).map(toValueInt).toSeq.sorted + } + + /** Remove keys (and corresponding values) where `time <= threshold` */ + protected def removeByKey(threshold: Long) + (implicit manager: SymmetricHashJoinStateManager): Long = { + manager match { + case evictByTimestamp: SupportsEvictByTimestamp => + evictByTimestamp.evictByTimestamp(threshold) + + case evictByCondition: SupportsEvictByCondition => + val expr = + LessThanOrEqual( + BoundReference( + 1, + inputValueAttributesWithWatermark.dataType, + inputValueAttributesWithWatermark.nullable), + Literal(threshold)) + evictByCondition.evictByKeyCondition(GeneratePredicate.generate(expr).eval _) + } + } + + /** Remove keys (and corresponding values) where `time <= threshold` */ + protected def removeAndReturnByKey(threshold: Long)( + implicit manager: SymmetricHashJoinStateManager): Iterator[KeyToValuePair] = { + manager match { + case evictByTimestamp: SupportsEvictByTimestamp => + evictByTimestamp.evictAndReturnByTimestamp(threshold) + + case evictByCondition: SupportsEvictByCondition => + val expr = + LessThanOrEqual( + BoundReference( + 1, + inputValueAttributesWithWatermark.dataType, + inputValueAttributesWithWatermark.nullable), + Literal(threshold)) + evictByCondition.evictAndReturnByKeyCondition(GeneratePredicate.generate(expr).eval _) + } + } + + /** Remove values where `time <= threshold` */ + protected def removeByValue(watermark: Long) + (implicit manager: SymmetricHashJoinStateManager): Long = { + manager match { + case evictByTimestamp: SupportsEvictByTimestamp => + evictByTimestamp.evictByTimestamp(watermark) + + case evictByCondition: SupportsEvictByCondition => + val expr = LessThanOrEqual(inputValueAttributesWithWatermark, Literal(watermark)) + evictByCondition.evictByValueCondition( + GeneratePredicate.generate(expr, inputValueAttributes).eval _) + } + } + + /** Remove values where `time <= threshold` */ + protected def removeAndReturnByValue(watermark: Long)( + implicit manager: SymmetricHashJoinStateManager): Iterator[KeyToValuePair] = { + manager match { + case evictByTimestamp: SupportsEvictByTimestamp => + evictByTimestamp.evictAndReturnByTimestamp(watermark) + + case evictByCondition: SupportsEvictByCondition => + val expr = LessThanOrEqual(inputValueAttributesWithWatermark, Literal(watermark)) + evictByCondition.evictAndReturnByValueCondition( + GeneratePredicate.generate(expr, inputValueAttributes).eval _) } } - SymmetricHashJoinStateManager.supportedVersions.foreach { version => + protected def assertNumRows(stateFormatVersion: Int, target: Long)( + implicit manager: SymmetricHashJoinStateManager): Unit = { + // This suite originally uses HDFSBackStateStoreProvider, which provides instantaneous metrics + // for numRows. + // But for version 3 with virtual column families, RocksDBStateStoreProvider updates metrics + // asynchronously. This means the number of keys obtained from the metrics are very likely + // to be outdated right after a put/remove. + if (stateFormatVersion <= 2) { + assert(manager.metrics.numKeys == target) + } + } + + protected def withJoinStateManager( + inputValueAttribs: Seq[Attribute], + joinKeyExprs: Seq[Expression], + stateFormatVersion: Int, + skipNullsForStreamStreamJoins: Boolean = false, + metric: Option[SQLMetric] = None) + (f: SymmetricHashJoinStateManager => Unit): Unit = { + // HDFS store providers do not support virtual column families + val storeProvider = if (stateFormatVersion >= 3) { + classOf[RocksDBStateStoreProvider].getName + } else { + classOf[HDFSBackedStateStoreProvider].getName + } + withTempDir { file => + withSQLConf( + SQLConf.STATE_STORE_SKIP_NULLS_FOR_STREAM_STREAM_JOINS.key -> + skipNullsForStreamStreamJoins.toString, + SQLConf.STATE_STORE_PROVIDER_CLASS.key -> storeProvider + ) { + val storeConf = new StateStoreConf(spark.sessionState.conf) + val stateInfo = StatefulOperatorStateInfo( + file.getAbsolutePath, UUID.randomUUID, 0, 0, 5, None) + val manager = SymmetricHashJoinStateManager( + LeftSide, inputValueAttribs, joinKeyExprs, Some(stateInfo), storeConf, new Configuration, + partitionId = 0, None, None, stateFormatVersion, metric, + joinStoreGenerator = new JoinStateManagerStoreGenerator()) + try { + f(manager) + } finally { + manager.abortIfNeeded() + } + } + } + StateStore.stop() + } + + protected def withJoinStateManagerWithCheckpointDir( + inputValueAttribs: Seq[Attribute], + joinKeyExprs: Seq[Expression], + stateFormatVersion: Int, + checkpointDir: File, + storeVersion: Int, + changelogCheckpoint: Boolean, + skipNullsForStreamStreamJoins: Boolean = false, + metric: Option[SQLMetric] = None) + (f: SymmetricHashJoinStateManager => Unit): Unit = { + // HDFS store providers do not support virtual column families + val storeProvider = if (stateFormatVersion >= 3) { + classOf[RocksDBStateStoreProvider].getName + } else { + classOf[HDFSBackedStateStoreProvider].getName + } + withSQLConf( + SQLConf.STATE_STORE_SKIP_NULLS_FOR_STREAM_STREAM_JOINS.key -> + skipNullsForStreamStreamJoins.toString, + SQLConf.STATE_STORE_PROVIDER_CLASS.key -> storeProvider, + "spark.sql.streaming.stateStore.rocksdb.changelogCheckpointing.enabled" -> + changelogCheckpoint.toString + ) { + val storeConf = new StateStoreConf(spark.sessionState.conf) + val stateInfo = StatefulOperatorStateInfo( + checkpointDir.getAbsolutePath, UUID.randomUUID, 0, storeVersion, 5, None) + val manager = SymmetricHashJoinStateManager( + LeftSide, inputValueAttribs, joinKeyExprs, Some(stateInfo), storeConf, new Configuration, + partitionId = 0, None, None, stateFormatVersion, metric, + joinStoreGenerator = new JoinStateManagerStoreGenerator()) + try { + f(manager) + } finally { + manager.abortIfNeeded() + } + } + StateStore.stop() + } +} + +class SymmetricHashJoinStateManagerSuite extends SymmetricHashJoinStateManagerBaseSuite { + private val watermarkMetadata = new MetadataBuilder() + .putLong(EventTimeWatermark.delayKey, 10).build() + private val inputValueSchema = new StructType() + .add(StructField("key", IntegerType)) + .add(StructField("time", IntegerType, metadata = watermarkMetadata)) + + override protected val inputValueAttributes = toAttributes(inputValueSchema) + override protected val inputValueAttributesWithWatermark = inputValueAttributes(1) + override protected val joinKeyExpressions = Seq[Expression]( + Literal(false), inputValueAttributes(0), Literal(10.0)) + + // V4 is excluded because it does not use indexed values (SupportsIndexedKeys) and therefore + // cannot have the null-hole problem that these tests exercise via updateNumValuesTestOnly. + // V4 is covered by EventTimeInKeySuite and EventTimeInValueSuite for standard operations. + private val versionsInTest = Seq(1, 2, 3) + + versionsInTest.foreach { version => test(s"StreamingJoinStateManager V${version} - all operations with nulls") { testAllOperationsWithNulls(version) } } - SymmetricHashJoinStateManager.supportedVersions.foreach { version => + versionsInTest.foreach { version => test(s"StreamingJoinStateManager V${version} - all operations with nulls in middle") { testAllOperationsWithNullsInMiddle(version) } } - SymmetricHashJoinStateManager.supportedVersions.foreach { version => + versionsInTest.foreach { version => test(s"SPARK-35689: StreamingJoinStateManager V${version} - " + "printable key of keyWithIndexToValue") { @@ -75,83 +277,23 @@ class SymmetricHashJoinStateManagerSuite extends StreamTest with BeforeAndAfter Literal(Timestamp.valueOf("2021-6-8 10:25:50"))) val keyGen = UnsafeProjection.create(keyExprs.map(_.dataType).toArray) - withJoinStateManager(inputValueAttribs, keyExprs, version) { manager => + withJoinStateManager(inputValueAttributes, keyExprs, version) { manager => + assert(manager.isInstanceOf[SupportsIndexedKeys]) + val currentKey = keyGen.apply(new GenericInternalRow(Array[Any]( false, 10.0, UTF8String.fromString("string"), Timestamp.valueOf("2021-6-8 10:25:50").getTime))) - val projectedRow = manager.getInternalRowOfKeyWithIndex(currentKey) + val projectedRow = manager.asInstanceOf[SupportsIndexedKeys] + .getInternalRowOfKeyWithIndex(currentKey) assert(s"$projectedRow" == "[false,10.0,string,1623173150000]") } } } - SymmetricHashJoinStateManager.supportedVersions.foreach { version => - test(s"Partition key extraction - SymmetricHashJoinStateManager v$version") { - testPartitionKeyExtraction(version) - } - } - - private def testAllOperations(stateFormatVersion: Int): Unit = { - withJoinStateManager(inputValueAttribs, joinKeyExprs, stateFormatVersion) { manager => - implicit val mgr = manager - - assert(get(20) === Seq.empty) // initially empty - append(20, 2) - assert(get(20) === Seq(2)) // should first value correctly - assertNumRows(stateFormatVersion, 1) - - append(20, 3) - assert(get(20) === Seq(2, 3)) // should append new values - append(20, 3) - assert(get(20) === Seq(2, 3, 3)) // should append another copy if same value added again - assertNumRows(stateFormatVersion, 3) - - assert(get(30) === Seq.empty) - append(30, 1) - assert(get(30) === Seq(1)) - assert(get(20) === Seq(2, 3, 3)) // add another key-value should not affect existing ones - assertNumRows(stateFormatVersion, 4) - - removeByKey(25) - assert(get(20) === Seq.empty) - assert(get(30) === Seq(1)) // should remove 20, not 30 - assertNumRows(stateFormatVersion, 1) - - removeByKey(30) - assert(get(30) === Seq.empty) // should remove 30 - assertNumRows(stateFormatVersion, 0) - - appendAndTest(40, 100, 200, 300) - appendAndTest(50, 125) - appendAndTest(60, 275) // prepare for testing removeByValue - assertNumRows(stateFormatVersion, 5) - - removeByValue(125) - assert(get(40) === Seq(200, 300)) - assert(get(50) === Seq.empty) - assert(get(60) === Seq(275)) // should remove only some values, not all - assertNumRows(stateFormatVersion, 3) - - append(40, 50) - assert(get(40) === Seq(50, 200, 300)) - assertNumRows(stateFormatVersion, 4) - - removeByValue(200) - assert(get(40) === Seq(300)) - assert(get(60) === Seq(275)) // should remove only some values, not all - assertNumRows(stateFormatVersion, 2) - - removeByValue(300) - assert(get(40) === Seq.empty) - assert(get(60) === Seq.empty) // should remove all values now - assertNumRows(stateFormatVersion, 0) - } - } - /* Test removeByValue with nulls simulated by updating numValues on the state manager */ private def testAllOperationsWithNulls(stateFormatVersion: Int): Unit = { - withJoinStateManager(inputValueAttribs, joinKeyExprs, stateFormatVersion) { manager => + withJoinStateManager(inputValueAttributes, joinKeyExpressions, stateFormatVersion) { manager => implicit val mgr = manager appendAndTest(40, 100, 200, 300) @@ -189,7 +331,7 @@ class SymmetricHashJoinStateManagerSuite extends StreamTest with BeforeAndAfter private def testAllOperationsWithNullsInMiddle(stateFormatVersion: Int): Unit = { // Test with skipNullsForStreamStreamJoins set to false which would throw a // NullPointerException while iterating and also return null values as part of get - withJoinStateManager(inputValueAttribs, joinKeyExprs, stateFormatVersion) { manager => + withJoinStateManager(inputValueAttributes, joinKeyExpressions, stateFormatVersion) { manager => implicit val mgr = manager val ex = intercept[Exception] { @@ -214,7 +356,7 @@ class SymmetricHashJoinStateManagerSuite extends StreamTest with BeforeAndAfter // Test with skipNullsForStreamStreamJoins set to true which would skip nulls // and continue iterating as part of removeByValue as well as get val metric = new SQLMetric("sum") - withJoinStateManager(inputValueAttribs, joinKeyExprs, stateFormatVersion, true, + withJoinStateManager(inputValueAttributes, joinKeyExpressions, stateFormatVersion, true, Some(metric)) { manager => implicit val mgr = manager @@ -245,200 +387,484 @@ class SymmetricHashJoinStateManagerSuite extends StreamTest with BeforeAndAfter } } - val watermarkMetadata = new MetadataBuilder().putLong(EventTimeWatermark.delayKey, 10).build() - val inputValueSchema = new StructType() - .add(StructField("time", IntegerType, metadata = watermarkMetadata)) - .add(StructField("value", BooleanType)) - val inputValueAttribs = toAttributes(inputValueSchema) - val inputValueAttribWithWatermark = inputValueAttribs(0) - val joinKeyExprs = Seq[Expression](Literal(false), inputValueAttribWithWatermark, Literal(10.0)) + protected def updateNumValues(key: Int, numValues: Long) + (implicit manager: SymmetricHashJoinStateManager): Unit = { + assert(manager.isInstanceOf[SupportsIndexedKeys]) + manager.asInstanceOf[SupportsIndexedKeys].updateNumValuesTestOnly(toJoinKeyRow(key), numValues) + } +} - val inputValueGen = UnsafeProjection.create(inputValueAttribs.map(_.dataType).toArray) - val joinKeyGen = UnsafeProjection.create(joinKeyExprs.map(_.dataType).toArray) +class SymmetricHashJoinStateManagerEventTimeInKeySuite + extends SymmetricHashJoinStateManagerBaseSuite { + private val versionsInTest = SymmetricHashJoinStateManager.supportedVersions - def toInputValue(i: Int): UnsafeRow = { - inputValueGen.apply(new GenericInternalRow(Array[Any](i, false))) + private val watermarkMetadata = new MetadataBuilder() + .putLong(EventTimeWatermark.delayKey, 10).build() + private val inputValueSchema = new StructType() + .add(StructField("time", IntegerType, metadata = watermarkMetadata)) + .add(StructField("value", IntegerType)) + + override protected val inputValueAttributes: Seq[AttributeReference] = + toAttributes(inputValueSchema) + override protected val inputValueAttributesWithWatermark: AttributeReference = + inputValueAttributes(0) + override protected val joinKeyExpressions: Seq[Expression] = Seq[Expression]( + Literal(false), + inputValueAttributesWithWatermark, + Literal(10.0)) + + versionsInTest.foreach { ver => + test(s"StreamingJoinStateManager V$ver - all operations") { + testAllOperations(ver) + } } - def toJoinKeyRow(i: Int): UnsafeRow = { - joinKeyGen.apply(new GenericInternalRow(Array[Any](false, i, 10.0))) + versionsInTest.foreach { ver => + test(s"StreamingJoinStateManager V$ver - all operations, with commit and load in between") { + testAllOperationsWithCommitAndLoad(ver, changelogCheckpoint = false) + testAllOperationsWithCommitAndLoad(ver, changelogCheckpoint = true) + } } - def toValueInt(inputValueRow: UnsafeRow): Int = inputValueRow.getInt(0) + private def testAllOperations(stateFormatVersion: Int): Unit = { + withJoinStateManager( + inputValueAttributes, + joinKeyExpressions, + stateFormatVersion = stateFormatVersion) { manager => + implicit val mgr = manager - def append(key: Int, value: Int)(implicit manager: SymmetricHashJoinStateManager): Unit = { - // we only put matched = false for simplicity - StreamingJoinSuite will test the functionality - manager.append(toJoinKeyRow(key), toInputValue(value), matched = false) + assert(get(20) === Seq.empty) // initially empty + append(20, 2) + assert(get(20) === Seq(2)) // should first value correctly + assertNumRows(stateFormatVersion, 1) + + append(20, 3) + assert(get(20) === Seq(2, 3)) // should append new values + append(20, 3) + assert(get(20) === Seq(2, 3, 3)) // should append another copy if same value added again + assertNumRows(stateFormatVersion, 3) + + assert(get(30) === Seq.empty) + append(30, 1) + assert(get(30) === Seq(1)) + assert(get(20) === Seq(2, 3, 3)) // add another key-value should not affect existing ones + assertNumRows(stateFormatVersion, 4) + + assert(removeByKey(25) === 3) + assert(get(20) === Seq.empty) + assert(get(30) === Seq(1)) // should remove 20, not 30 + assertNumRows(stateFormatVersion, 1) + + assert(removeByKey(30) === 1) + assert(get(30) === Seq.empty) // should remove 30 + assertNumRows(stateFormatVersion, 0) + } } - def appendAndTest(key: Int, values: Int*) - (implicit manager: SymmetricHashJoinStateManager): Unit = { - values.foreach { value => append(key, value)} - require(get(key) === values) + private def testAllOperationsWithCommitAndLoad( + stateFormatVersion: Int, + changelogCheckpoint: Boolean): Unit = { + withTempDir { checkpointDir => + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, + joinKeyExpressions, + stateFormatVersion = stateFormatVersion, + checkpointDir, + storeVersion = 0, + changelogCheckpoint = changelogCheckpoint) { manager => + + implicit val mgr = manager + + assert(get(20) === Seq.empty) // initially empty + append(20, 2) + assert(get(20) === Seq(2)) // should first value correctly + + append(20, 3) + assert(get(20) === Seq(2, 3)) // should append new values + append(20, 3) + assert(get(20) === Seq(2, 3, 3)) // should append another copy if same value added again + + mgr.commit() + } + + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, + joinKeyExpressions, + stateFormatVersion = stateFormatVersion, + checkpointDir, + storeVersion = 1, + changelogCheckpoint = changelogCheckpoint) { manager => + + implicit val mgr = manager + + assert(get(30) === Seq.empty) + append(30, 1) + assert(get(30) === Seq(1)) + assert(get(20) === Seq(2, 3, 3)) // add another key-value should not affect existing ones + + assert(removeByKey(25) === 3) + assert(get(20) === Seq.empty) + assert(get(30) === Seq(1)) // should remove 20, not 30 + + mgr.commit() + } + + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, + joinKeyExpressions, + stateFormatVersion = stateFormatVersion, + checkpointDir, + storeVersion = 2, + changelogCheckpoint = changelogCheckpoint) { manager => + + implicit val mgr = manager + + assert(removeByKey(30) === 1) + assert(get(30) === Seq.empty) // should remove 30 + + mgr.commit() + } + } } - def updateNumValues(key: Int, numValues: Long) - (implicit manager: SymmetricHashJoinStateManager): Unit = { - manager.updateNumValuesTestOnly(toJoinKeyRow(key), numValues) + versionsInTest.foreach { ver => + test(s"StreamingJoinStateManager V$ver - evictAndReturnByKey returns correct rows") { + withJoinStateManager( + inputValueAttributes, joinKeyExpressions, stateFormatVersion = ver) { manager => + implicit val mgr = manager + + append(20, 2) + append(20, 3) + append(30, 1) + + val evicted = removeAndReturnByKey(25) + val evictedPairs = evicted.map(p => (toValueInt(p.value), p.matched)).toSeq + assert(evictedPairs.map(_._1).sorted === Seq(2, 3)) + assert(evictedPairs.forall(!_._2)) + + assert(get(20) === Seq.empty) + assert(get(30) === Seq(1)) + } + } } - def getNumValues(key: Int) - (implicit manager: SymmetricHashJoinStateManager): Int = { - manager.get(toJoinKeyRow(key)).size + // V1 excluded: V1 converter does not persist matched flags (SPARK-26154) + versionsInTest.filter(_ >= 2).foreach { ver => + test(s"StreamingJoinStateManager V$ver - matched flag update + eviction roundtrip") { + withTempDir { checkpointDir => + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, joinKeyExpressions, ver, + checkpointDir, storeVersion = 0, changelogCheckpoint = false) { manager => + implicit val mgr = manager + + append(20, 2) + append(20, 3) + append(30, 1) + + val dummyRow = new GenericInternalRow(0) + val matched = manager.getJoinedRows( + toJoinKeyRow(20), + row => new JoinedRow(row, dummyRow), + jr => jr.getInt(1) == 2 + ).toSeq + // Here we ensure consumption of the iterator provided by getJoinedRows. + assert(matched.size == 1) + + mgr.commit() + } + + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, joinKeyExpressions, ver, + checkpointDir, storeVersion = 1, changelogCheckpoint = false) { manager => + implicit val mgr = manager + + val evicted = removeAndReturnByKey(25) + val evictedPairs = evicted.map(p => (toValueInt(p.value), p.matched)).toSeq + val matchedByValue = evictedPairs.toMap + assert(matchedByValue(2) === true) + assert(matchedByValue(3) === false) + + mgr.commit() + } + } + } } - def get(key: Int)(implicit manager: SymmetricHashJoinStateManager): Seq[Int] = { - manager.get(toJoinKeyRow(key)).map(toValueInt).toSeq.sorted + // V1 excluded: V1 converter does not persist matched flags (SPARK-26154) + versionsInTest.filter(_ >= 2).foreach { ver => + test(s"StreamingJoinStateManager V$ver - " + + "getJoinedRows with excludeRowsAlreadyMatched") { + withJoinStateManager( + inputValueAttributes, joinKeyExpressions, stateFormatVersion = ver) { manager => + implicit val mgr = manager + + append(20, 2) + append(20, 3) + append(20, 4) + + val dummyRow = new GenericInternalRow(0) + val firstPass = manager.getJoinedRows( + toJoinKeyRow(20), + row => new JoinedRow(row, dummyRow), + // intentionally exclude 4, which should be only returned in next pass + jr => jr.getInt(1) < 4 + ).toSeq + assert(firstPass.size == 2) + + val secondPass = manager.getJoinedRows( + toJoinKeyRow(20), + row => new JoinedRow(row, dummyRow), + _ => true, + excludeRowsAlreadyMatched = true + ).map(_.getInt(1)).toSeq + assert(secondPass === Seq(4)) + } + } } +} - /** Remove keys (and corresponding values) where `time <= threshold` */ - def removeByKey(threshold: Long)(implicit manager: SymmetricHashJoinStateManager): Unit = { - val expr = - LessThanOrEqual( - BoundReference( - 1, inputValueAttribWithWatermark.dataType, inputValueAttribWithWatermark.nullable), - Literal(threshold)) - val iter = manager.removeByKeyCondition(GeneratePredicate.generate(expr).eval _) - while (iter.hasNext) iter.next() +class SymmetricHashJoinStateManagerEventTimeInValueSuite + extends SymmetricHashJoinStateManagerBaseSuite { + + private val versionsInTest = SymmetricHashJoinStateManager.supportedVersions + + private val watermarkMetadata = new MetadataBuilder() + .putLong(EventTimeWatermark.delayKey, 10).build() + private val inputValueSchema = new StructType() + .add(StructField("key", IntegerType)) + .add(StructField("time", IntegerType, metadata = watermarkMetadata)) + + protected override val inputValueAttributes = toAttributes(inputValueSchema) + protected override val inputValueAttributesWithWatermark = inputValueAttributes(1) + protected override val joinKeyExpressions = Seq[Expression]( + Literal(false), inputValueAttributes(0), Literal(10.0)) + + versionsInTest.foreach { ver => + test(s"StreamingJoinStateManager V$ver - all operations") { + testAllOperations(ver) + } } - /** Remove values where `time <= threshold` */ - def removeByValue(watermark: Long)(implicit manager: SymmetricHashJoinStateManager): Unit = { - val expr = LessThanOrEqual(inputValueAttribWithWatermark, Literal(watermark)) - val iter = manager.removeByValueCondition( - GeneratePredicate.generate(expr, inputValueAttribs).eval _) - while (iter.hasNext) iter.next() + versionsInTest.foreach { ver => + test(s"StreamingJoinStateManager V$ver - all operations, with commit and load in between") { + testAllOperationsWithCommitAndLoad(ver, changelogCheckpoint = false) + testAllOperationsWithCommitAndLoad(ver, changelogCheckpoint = true) + } } - def assertNumRows(stateFormatVersion: Int, target: Long)( - implicit manager: SymmetricHashJoinStateManager): Unit = { - // This suite originally uses HDFSBackStateStoreProvider, which provides instantaneous metrics - // for numRows. - // But for version 3 with virtual column families, RocksDBStateStoreProvider updates metrics - // asynchronously. This means the number of keys obtained from the metrics are very likely - // to be outdated right after a put/remove. - if (stateFormatVersion <= 2) { - assert(manager.metrics.numKeys == target) + private def testAllOperations(stateFormatVersion: Int): Unit = { + withJoinStateManager( + inputValueAttributes, + joinKeyExpressions, + stateFormatVersion = stateFormatVersion) { manager => + implicit val mgr = manager + + appendAndTest(40, 100, 200, 300) + appendAndTest(50, 125) + appendAndTest(60, 275) // prepare for testing removeByValue + assertNumRows(stateFormatVersion, 5) + + assert(removeByValue(125) === 2) + assert(get(40) === Seq(200, 300)) + assert(get(50) === Seq.empty) + assert(get(60) === Seq(275)) // should remove only some values, not all + assertNumRows(stateFormatVersion, 3) + + append(40, 50) + assert(get(40) === Seq(50, 200, 300)) + assertNumRows(stateFormatVersion, 4) + + assert(removeByValue(200) === 2) + assert(get(40) === Seq(300)) + assert(get(60) === Seq(275)) // should remove only some values, not all + assertNumRows(stateFormatVersion, 2) + + assert(removeByValue(300) === 2) + assert(get(40) === Seq.empty) + assert(get(60) === Seq.empty) // should remove all values now + assertNumRows(stateFormatVersion, 0) } } - def withJoinStateManager( - inputValueAttribs: Seq[Attribute], - joinKeyExprs: Seq[Expression], + private def testAllOperationsWithCommitAndLoad( stateFormatVersion: Int, - skipNullsForStreamStreamJoins: Boolean = false, - metric: Option[SQLMetric] = None) - (f: SymmetricHashJoinStateManager => Unit): Unit = { - // HDFS store providers do not support virtual column families - val storeProvider = if (stateFormatVersion == 3) { - classOf[RocksDBStateStoreProvider].getName - } else { - classOf[HDFSBackedStateStoreProvider].getName - } - withTempDir { file => - withSQLConf( - SQLConf.STATE_STORE_SKIP_NULLS_FOR_STREAM_STREAM_JOINS.key -> - skipNullsForStreamStreamJoins.toString, - SQLConf.STATE_STORE_PROVIDER_CLASS.key -> storeProvider - ) { - val storeConf = new StateStoreConf(spark.sessionState.conf) - val stateInfo = StatefulOperatorStateInfo( - file.getAbsolutePath, UUID.randomUUID, 0, 0, 5, None) - val manager = SymmetricHashJoinStateManager( - LeftSide, inputValueAttribs, joinKeyExprs, Some(stateInfo), storeConf, new Configuration, - partitionId = 0, None, None, stateFormatVersion, metric, - joinStoreGenerator = new JoinStateManagerStoreGenerator()) - try { - f(manager) - } finally { - manager.abortIfNeeded() - } + changelogCheckpoint: Boolean): Unit = { + withTempDir { checkpointDir => + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, + joinKeyExpressions, + stateFormatVersion = stateFormatVersion, + checkpointDir, + storeVersion = 0, + changelogCheckpoint = changelogCheckpoint) { manager => + + implicit val mgr = manager + + appendAndTest(40, 100, 200, 300) + appendAndTest(50, 125) + appendAndTest(60, 275) // prepare for testing removeByValue + + mgr.commit() + } + + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, + joinKeyExpressions, + stateFormatVersion = stateFormatVersion, + checkpointDir, + storeVersion = 1, + changelogCheckpoint = changelogCheckpoint) { manager => + + implicit val mgr = manager + + assert(removeByValue(125) === 2) + assert(get(40) === Seq(200, 300)) + assert(get(50) === Seq.empty) + assert(get(60) === Seq(275)) // should remove only some values, not all + + mgr.commit() + } + + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, + joinKeyExpressions, + stateFormatVersion = stateFormatVersion, + checkpointDir, + storeVersion = 2, + changelogCheckpoint = changelogCheckpoint) { manager => + + implicit val mgr = manager + + append(40, 50) + assert(get(40) === Seq(50, 200, 300)) + + mgr.commit() + } + + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, + joinKeyExpressions, + stateFormatVersion = stateFormatVersion, + checkpointDir, + storeVersion = 3, + changelogCheckpoint = changelogCheckpoint) { manager => + + implicit val mgr = manager + + assert(removeByValue(200) === 2) + assert(get(40) === Seq(300)) + assert(get(60) === Seq(275)) // should remove only some values, not all + + mgr.commit() + } + + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, + joinKeyExpressions, + stateFormatVersion = stateFormatVersion, + checkpointDir, + storeVersion = 4, + changelogCheckpoint = changelogCheckpoint) { manager => + + implicit val mgr = manager + + assert(removeByValue(300) === 2) + assert(get(40) === Seq.empty) + assert(get(60) === Seq.empty) // should remove all values now + + mgr.commit() } } - StateStore.stop() } - private def testPartitionKeyExtraction(stateFormatVersion: Int): Unit = { - withJoinStateManager(inputValueAttribs, joinKeyExprs, stateFormatVersion) { manager => - implicit val mgr = manager + versionsInTest.foreach { ver => + test(s"StreamingJoinStateManager V$ver - evictAndReturnByValue returns correct rows") { + withJoinStateManager( + inputValueAttributes, joinKeyExpressions, stateFormatVersion = ver) { manager => + implicit val mgr = manager - val joinKeySchema = StructType( - joinKeyExprs.zipWithIndex.map { case (expr, i) => - StructField(s"field$i", expr.dataType, expr.nullable) - }) - - // Add some test data - append(key = 20, value = 100) - append(key = 20, value = 200) - append(key = 30, value = 150) - - Seq( - (getKeyToNumValuesStoreAndKeySchema(), SymmetricHashJoinStateManager - .getStateStoreName(LeftSide, SymmetricHashJoinStateManager.KeyToNumValuesType), - // expect 1 for both key 20 & 30 - 1, 1), - (getKeyWithIndexToValueStoreAndKeySchema(), SymmetricHashJoinStateManager - .getStateStoreName(LeftSide, SymmetricHashJoinStateManager.KeyWithIndexToValueType), - // expect 2 for key 20 & 1 for key 30 - 2, 1) - ).foreach { case ((store, keySchema), name, expectedNumKey20, expectedNumKey30) => - val storeName = if (stateFormatVersion == 3) { - StateStoreId.DEFAULT_STORE_NAME - } else { - name - } + appendAndTest(40, 100, 200, 300) + appendAndTest(50, 125) + appendAndTest(60, 275) - val colFamilyName = if (stateFormatVersion == 3) { - name - } else { - StateStore.DEFAULT_COL_FAMILY_NAME - } + val evicted = removeAndReturnByValue(125) + val evictedPairs = evicted.map(p => (toValueInt(p.value), p.matched)).toSeq + assert(evictedPairs.map(_._1).sorted === Seq(100, 125)) + assert(evictedPairs.forall(!_._2)) - val extractor = StatePartitionKeyExtractorFactory.create( - StatefulOperatorsUtils.SYMMETRIC_HASH_JOIN_EXEC_OP_NAME, - keySchema, - storeName, - colFamilyName, - stateFormatVersion = Some(stateFormatVersion) - ) - - assert(extractor.partitionKeySchema === joinKeySchema, - "Partition key schema should match the join key schema") - - // Copy both the state key and partition key to avoid UnsafeRow reuse issues - val stateKeys = store.iterator(colFamilyName).map(_.key.copy()).toList - val partitionKeys = stateKeys.map(extractor.partitionKey(_).copy()) - - assert(partitionKeys.length === expectedNumKey20 + expectedNumKey30, - "Should have same num partition keys as num state store keys") - assert(partitionKeys.count(_ === toJoinKeyRow(20)) === expectedNumKey20, - "Should have the expected num partition keys for join key 20") - assert(partitionKeys.count(_ === toJoinKeyRow(30)) === expectedNumKey30, - "Should have the expected num partition keys for join key 30") + assert(get(40) === Seq(200, 300)) + assert(get(50) === Seq.empty) + assert(get(60) === Seq(275)) } } } - def getKeyToNumValuesStoreAndKeySchema() - (implicit manager: SymmetricHashJoinStateManager): (StateStore, StructType) = { - val keyToNumValuesHandler = manager.keyToNumValues - val keyToNumValuesStoreMethod = PrivateMethod[StateStore](Symbol("stateStore")) - val keyToNumValuesStore = keyToNumValuesHandler.invokePrivate(keyToNumValuesStoreMethod()) + // V1 excluded: V1 converter does not persist matched flags (SPARK-26154) + versionsInTest.filter(_ >= 2).foreach { ver => + test(s"StreamingJoinStateManager V$ver - matched flag update + eviction roundtrip") { + withTempDir { checkpointDir => + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, joinKeyExpressions, ver, + checkpointDir, storeVersion = 0, changelogCheckpoint = false) { manager => + implicit val mgr = manager + + appendAndTest(40, 100, 200, 300) + + val dummyRow = new GenericInternalRow(0) + val matched = manager.getJoinedRows( + toJoinKeyRow(40), + row => new JoinedRow(row, dummyRow), + jr => jr.getInt(1) == 100 + ).toSeq + assert(matched.size == 1) + + mgr.commit() + } - (keyToNumValuesStore, manager.keySchema) - } + withJoinStateManagerWithCheckpointDir( + inputValueAttributes, joinKeyExpressions, ver, + checkpointDir, storeVersion = 1, changelogCheckpoint = false) { manager => + implicit val mgr = manager - def getKeyWithIndexToValueStoreAndKeySchema() - (implicit manager: SymmetricHashJoinStateManager): (StateStore, StructType) = { - val keyWithIndexToValueHandler = manager.keyWithIndexToValue + val evicted = removeAndReturnByValue(125) + val evictedPairs = evicted.map(p => (toValueInt(p.value), p.matched)).toSeq + val matchedByValue = evictedPairs.toMap + assert(matchedByValue(100) === true) - val keyWithIndexToValueStoreMethod = PrivateMethod[StateStore](Symbol("stateStore")) - val keyWithIndexToValueStore = - keyWithIndexToValueHandler.invokePrivate(keyWithIndexToValueStoreMethod()) + mgr.commit() + } + } + } + } - val keySchemaMethod = PrivateMethod[StructType](Symbol("keyWithIndexSchema")) - val keyWithIndexToValueKeySchema = keyWithIndexToValueHandler.invokePrivate(keySchemaMethod()) - (keyWithIndexToValueStore, keyWithIndexToValueKeySchema) + // V1 excluded: V1 converter does not persist matched flags (SPARK-26154) + versionsInTest.filter(_ >= 2).foreach { ver => + test(s"StreamingJoinStateManager V$ver - " + + "getJoinedRows with excludeRowsAlreadyMatched") { + withJoinStateManager( + inputValueAttributes, joinKeyExpressions, stateFormatVersion = ver) { manager => + implicit val mgr = manager + + appendAndTest(40, 100, 200, 300) + + val dummyRow = new GenericInternalRow(0) + val firstPass = manager.getJoinedRows( + toJoinKeyRow(40), + row => new JoinedRow(row, dummyRow), + // intentionally exclude 300, which should be only returned in next pass + jr => jr.getInt(1) < 300 + ).toSeq + assert(firstPass.size == 2) + + val secondPass = manager.getJoinedRows( + toJoinKeyRow(40), + row => new JoinedRow(row, dummyRow), + _ => true, + excludeRowsAlreadyMatched = true + ).map(_.getInt(1)).toSeq + assert(secondPass === Seq(300)) + } + } } } From 1b1904ec9f790398e53d95fe6d0e3f3bec18d5a3 Mon Sep 17 00:00:00 2001 From: Yicong-Huang <17627829+Yicong-Huang@users.noreply.github.com> Date: Fri, 27 Feb 2026 13:16:17 +0800 Subject: [PATCH 073/130] [SPARK-55405][PYTHON][TESTS][FOLLOW-UP] Add macOS ARM overrides for float-to-int unsafe cast golden file mismatches ### What changes were proposed in this pull request? Add macOS ARM-specific overrides in `_overrides_unsafe()` for 7 float-to-int unsafe cast cases that differ between Linux ARM and macOS ARM due to LLVM code generation differences. This fixes the `build_python_3.12_macos26` CI workflow which has been failing on every run. ### Why are the changes needed? Fix macOS 26 CI failures. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Tested on macOS 26 (Darwin 25.2.0, arm64) with PyArrow 22.0.0. Also tested in CI: https://github.com/Yicong-Huang/spark/actions/runs/22465733224 ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54525 from Yicong-Huang/SPARK-55405/fix/macos26-arm-float-int-cast-overrides. Authored-by: Yicong-Huang <17627829+Yicong-Huang@users.noreply.github.com> Signed-off-by: Ruifeng Zheng --- .../pyarrow/test_pyarrow_array_cast.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/python/pyspark/tests/upstream/pyarrow/test_pyarrow_array_cast.py b/python/pyspark/tests/upstream/pyarrow/test_pyarrow_array_cast.py index b182e254b90f1..6242a6d784dad 100644 --- a/python/pyspark/tests/upstream/pyarrow/test_pyarrow_array_cast.py +++ b/python/pyspark/tests/upstream/pyarrow/test_pyarrow_array_cast.py @@ -587,6 +587,27 @@ def f16_repr(values): } ) + if platform.system() == "Darwin": + # macOS ARM differs from Linux ARM for some unsafe casts due to + # differences in LLVM code generation between the two platforms. + overrides.update( + { + # negative float → uint8/uint16: macOS ARM wraps (255/65535), + # Linux ARM saturates to 0 + ("float16:standard", "uint8"): "[0, 1, 255, None]@uint8", + ("float16:standard", "uint16"): "[0, 1, 65535, None]@uint16", + ("float32:standard", "uint8"): "[0, 1, 255, None]@uint8", + ("float64:standard", "uint8"): "[0, 1, 255, None]@uint8", + ("float64:standard", "uint16"): "[0, 1, 65535, None]@uint16", + # negative float → uint32: macOS ARM saturates to 0, + # Linux ARM wraps to 4294967295 (matching x86 golden) + ("float64:standard", "uint32"): "[0, 1, 0, None]@uint32", + # special float → int32: macOS ARM saturates (INT32_MAX/MIN), + # Linux ARM gives -1/0 + ("float64:special", "int32"): "[2147483647, -2147483648, 0, None]@int32", + } + ) + return overrides # ----- test methods ----- From c26d0bc726eaf04f1270cef36c340df098b486e2 Mon Sep 17 00:00:00 2001 From: zeruibao Date: Fri, 27 Feb 2026 14:25:30 +0900 Subject: [PATCH 074/130] [SPARK-55701][SS] Fix race condition in CompactibleFileStreamLog.allFiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? Changed the exception type thrown in `CompactibleFileStreamLog.allFiles()` from `IllegalStateException` to `FileNotFoundException` when a batch metadata file is missing (line 270). Since `FileNotFoundException` extends `IOException`, the existing retry loop (line 277) now catches this case and retries with an updated `latestId`. ### Why are the changes needed? There is a race condition between a batch reader (e.g., `DESCRIBE TABLE` via Thrift server) and a streaming writer performing compaction + cleanup concurrently: 1. The reader calls `getLatestBatchId()` and observes `latestId = N`. 2. The writer completes a new compaction batch and `deleteExpiredLog` removes old batch files. 3. The reader tries to read the now-deleted batch files based on the stale `latestId`. The `allFiles()` method already has a retry loop designed to handle this exact scenario — it catches `IOException`, refreshes `latestId`, and retries. However, the missing-file case was throwing `IllegalStateException`, which is not a subclass of `IOException`, so it escaped the retry loop entirely and surfaced as a fatal error to the user. The fix changes the exception to `FileNotFoundException` so the existing retry logic handles it correctly. The safety check on re-throw (lines 284-286) ensures that if no newer compaction exists, the exception is still propagated rather than silently swallowed. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? UT ### Was this patch authored or co-authored using generative AI tooling? Get help with Claude 4.6 Opus but also review it carefully. Closes #54500 from zeruibao/SPARK-55701-fix-race-condition. Authored-by: zeruibao Signed-off-by: Jungtaek Lim --- .../runtime/CompactibleFileStreamLog.scala | 2 +- .../CompactibleFileStreamLogSuite.scala | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/CompactibleFileStreamLog.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/CompactibleFileStreamLog.scala index 8a90982b7c0c6..7efe7b52c7abe 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/CompactibleFileStreamLog.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/runtime/CompactibleFileStreamLog.scala @@ -267,7 +267,7 @@ abstract class CompactibleFileStreamLog[T <: AnyRef : ClassTag]( val logs = getAllValidBatches(latestId, compactInterval).flatMap { id => filterInBatch(id)(shouldRetain(_, curTime)).getOrElse { - throw new IllegalStateException( + throw new FileNotFoundException( s"${batchIdToPath(id)} doesn't exist " + s"(latestId: $latestId, compactInterval: $compactInterval)") } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/CompactibleFileStreamLogSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/CompactibleFileStreamLogSuite.scala index 5a1608cb6165a..b1b1976dff8bd 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/CompactibleFileStreamLogSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/CompactibleFileStreamLogSuite.scala @@ -258,6 +258,55 @@ class CompactibleFileStreamLogSuite extends SharedSparkSession { }) } + test("allFiles retries when compaction deletes batch files during read") { + withTempDir { dir => + // Override getLatestBatchId() so the first call returns a stale value (4), + // simulating the reader listing the directory before compaction batch 5 is visible. + // The retry in allFiles() calls super.getLatestBatchId() (statically bound to + // HDFSMetadataLog), which bypasses this override and reads the real filesystem. + @volatile var staleLatestId: Option[Long] = None + val compactibleLog = new FakeCompactibleFileStreamLog( + FakeCompactibleFileStreamLog.VERSION, + _fileCleanupDelayMs = Long.MaxValue, + _defaultCompactInterval = 3, + _defaultMinBatchesToRetain = 1, + spark, + dir.getCanonicalPath) { + override def getLatestBatchId(): Option[Long] = { + staleLatestId match { + case some @ Some(_) => + staleLatestId = None + some + case None => + super.getLatestBatchId() + } + } + } + + val fs = compactibleLog.metadataPath.getFileSystem(spark.sessionState.newHadoopConf()) + + for (batchId <- 0 to 5) { + compactibleLog.add(batchId, Array("path_" + batchId)) + } + + // Delete old files as if a concurrent writer's deleteExpiredLog removed them + // after writing compaction batch 5. + fs.delete(compactibleLog.batchIdToPath(2), false) + fs.delete(compactibleLog.batchIdToPath(3), false) + fs.delete(compactibleLog.batchIdToPath(4), false) + + // Inject stale latestId=4 right before calling allFiles(). + // First iteration: getLatestBatchId() returns 4 (stale). + // getAllValidBatches(4, 3) = [2, 3, 4]. Batch 2 is deleted -> FileNotFoundException. + // Retry: super.getLatestBatchId() reads filesystem -> returns 5. + // nextCompactionBatchId(4, 3) = 5, and 5 >= 5, so retry proceeds. + // Second iteration: getAllValidBatches(5, 3) = [5]. Reads 5.compact -> success. + staleLatestId = Some(4L) + val result = compactibleLog.allFiles() + assert(result === (0 to 5).map("path_" + _)) + } + } + private def withFakeCompactibleFileStreamLog( fileCleanupDelayMs: Long, defaultCompactInterval: Int, From 555cd3846caca13bf92be601a04c29fb8e56e555 Mon Sep 17 00:00:00 2001 From: David Tagatac Date: Fri, 27 Feb 2026 14:39:57 +0900 Subject: [PATCH 075/130] [SPARK-55645][SQL] Add serdeName to CatalogStorageFormat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? - Add `serdeName` to `org.apache.spark.sql.catalyst.catalog.CatalogStorageFormat`. - Include this field when responding to `DESCRIBE EXTENDED` queries. - Handle this field when parsing table details from the Hive Metastore API and when writing back to it. ### Why are the changes needed? - This field is included in [`SerDeInfo`](https://github.com/apache/hive/blob/5160d3af392248255f68e41e1e0557eae4d95273/metastore/if/hive_metastore.thrift#L260) returned by the Hive Metastore API. - Its omission in the internal representation of Hive tables makes it cumbersome to consume this field. Before this change: ``` private def hasExampleSerdeName(h: HiveTableRelation): Boolean = { val key = (h.tableMeta.database, h.tableMeta.identifier.table) serdeNameCache.computeIfAbsent(key, _ => { val catalog = session.sharedState.externalCatalog.unwrapped .asInstanceOf[HiveExternalCatalog] catalog.client.getRawHiveTableOption(key._1, key._2).exists { rawHiveTable => // Use reflection to access SerDeInfo.name across classloader boundaries, // so that this works even when spark.sql.hive.metastore.jars is configured. val rawTable = rawHiveTable.rawTable val tTable = rawTable.getClass.getMethod("getTTable").invoke(rawTable) val sd = tTable.getClass.getMethod("getSd").invoke(tTable) val serdeInfo = sd.getClass.getMethod("getSerdeInfo").invoke(sd) val name = serdeInfo.getClass.getMethod("getName").invoke(serdeInfo) name == ExampleSerdeInfoName } }) } ``` After this change: ``` private def hasExampleSerdeName(h: HiveTableRelation): Boolean = { h.tableMeta.storage.serdeName.contains(ExampleSerdeInfoName) } ``` ### Does this PR introduce _any_ user-facing change? Yes, developers can now access `CatalogStorageFormat.serdeName`, representing the Hive Metastore API field `SerDeInfo.name`, when interacting with Spark representations of Hive tables. ### How was this patch tested? - Unit test added. - `DESCRIBE EXTENDED` run via `spark-shell` returns "Serde Name" properly for a Hive table with a Serde name: ``` scala> spark.sql("CREATE TABLE t (d1 DECIMAL(10,3), d2 STRING) STORED AS TEXTFILE;").show() ++ || ++ ++ scala> spark.sql("DESCRIBE EXTENDED t;").show() +--------------------+--------------------+-------+ | col_name| data_type|comment| +--------------------+--------------------+-------+ | d1| decimal(10,3)| NULL| | d2| string| NULL| | | | | |# Detailed Table ...| | | ... | Location|file:/local/home/...| | | Serde Library|org.apache.hadoop...| | ... +--------------------+--------------------+-------+ scala> import org.apache.spark.sql.catalyst.TableIdentifier import org.apache.spark.sql.catalyst.TableIdentifier scala> val hiveTable = spark.sessionState.catalog.getTableMetadata(TableIdentifier("t", Some("default"))) val hiveTable: org.apache.spark.sql.catalyst.catalog.CatalogTable = ... scala> val updated = hiveTable.copy(storage = hiveTable.storage.copy(serdeName = Some("testSerdeName"))) val updated: org.apache.spark.sql.catalyst.catalog.CatalogTable = ... scala> spark.sessionState.catalog.alterTable(updated) scala> spark.sql("DESCRIBE EXTENDED t;").show() +--------------------+--------------------+-------+ | col_name| data_type|comment| +--------------------+--------------------+-------+ | d1| decimal(10,3)| NULL| | d2| string| NULL| | | | | |# Detailed Table ...| | | ... | Location|file:/local/home/...| | | Serde Name| testSerdeName| | | Serde Library|org.apache.hadoop...| | ... +--------------------+--------------------+-------+ ``` ### Was this patch authored or co-authored using generative AI tooling? No. *This contribution is my original work, and I license the work to the Spark project under the project’s open source license.* Closes #54467 from tagatac/serde-name. Authored-by: David Tagatac Signed-off-by: Kousuke Saruta --- .../spark/sql/catalyst/catalog/interface.scala | 9 ++++++--- .../catalog/ExternalCatalogEventSuite.scala | 1 + .../catalyst/catalog/ExternalCatalogSuite.scala | 7 ++++--- .../spark/sql/AlwaysPersistedConfigsSuite.scala | 2 +- .../spark/sql/execution/command/DDLSuite.scala | 2 +- .../apache/spark/sql/sources/InsertSuite.scala | 2 ++ .../spark/sql/hive/HiveMetastoreCatalog.scala | 3 +++ .../spark/sql/hive/client/HiveClientImpl.scala | 4 ++++ .../sql/hive/HiveMetastoreCatalogSuite.scala | 15 +++++++++++++++ .../spark/sql/hive/HiveSchemaInferenceSuite.scala | 1 + .../sql/hive/MetastoreDataSourcesSuite.scala | 1 + .../spark/sql/hive/client/HiveClientSuite.scala | 3 +++ .../hive/client/HivePartitionFilteringSuite.scala | 1 + .../spark/sql/hive/execution/HiveDDLSuite.scala | 2 ++ 14 files changed, 45 insertions(+), 8 deletions(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/interface.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/interface.scala index fcaea47095040..8ad01e54ae9b6 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/interface.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/interface.scala @@ -144,6 +144,7 @@ case class CatalogStorageFormat( locationUri: Option[URI], inputFormat: Option[String], outputFormat: Option[String], + serdeName: Option[String], serde: Option[String], compressed: Boolean, properties: Map[String, String]) extends MetadataMapSupport { @@ -158,6 +159,7 @@ case class CatalogStorageFormat( val map = mutable.LinkedHashMap[String, JValue]() locationUri.foreach(l => map += ("Location" -> JString(CatalogUtils.URIToString(l)))) + serdeName.foreach(s => map += ("Serde Name" -> JString(s))) serde.foreach(s => map += ("Serde Library" -> JString(s))) inputFormat.foreach(format => map += ("InputFormat" -> JString(format))) outputFormat.foreach(format => map += ("OutputFormat" -> JString(format))) @@ -178,8 +180,8 @@ case class CatalogStorageFormat( object CatalogStorageFormat { /** Empty storage format for default values and copies. */ - val empty = CatalogStorageFormat(locationUri = None, inputFormat = None, - outputFormat = None, serde = None, compressed = false, properties = Map.empty) + val empty = CatalogStorageFormat(locationUri = None, inputFormat = None, outputFormat = None, + serdeName = None, serde = None, compressed = false, properties = Map.empty) } /** @@ -614,10 +616,11 @@ case class CatalogTable( inputFormat: Option[String] = storage.inputFormat, outputFormat: Option[String] = storage.outputFormat, compressed: Boolean = false, + serdeName: Option[String] = storage.serdeName, serde: Option[String] = storage.serde, properties: Map[String, String] = storage.properties): CatalogTable = { copy(storage = CatalogStorageFormat( - locationUri, inputFormat, outputFormat, serde, compressed, properties)) + locationUri, inputFormat, outputFormat, serdeName, serde, compressed, properties)) } def toJsonLinkedHashMap: mutable.LinkedHashMap[String, JValue] = { diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/catalog/ExternalCatalogEventSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/catalog/ExternalCatalogEventSuite.scala index f332393e503f9..12e9cd790ca6f 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/catalog/ExternalCatalogEventSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/catalog/ExternalCatalogEventSuite.scala @@ -247,6 +247,7 @@ class ExternalCatalogEventSuite extends SparkFunSuite { locationUri = Some(tableUri), inputFormat = Some("tableInputFormat"), outputFormat = Some("tableOutputFormat"), + serdeName = None, serde = None, compressed = false, properties = Map.empty) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/catalog/ExternalCatalogSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/catalog/ExternalCatalogSuite.scala index f06128f236792..0a9e370e6b219 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/catalog/ExternalCatalogSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/catalog/ExternalCatalogSuite.scala @@ -911,7 +911,7 @@ abstract class ExternalCatalogSuite extends SparkFunSuite { tableType = CatalogTableType.EXTERNAL, storage = CatalogStorageFormat( Some(Utils.createTempDir().toURI), - None, None, None, false, Map.empty), + None, None, None, None, false, Map.empty), schema = new StructType().add("a", "int").add("b", "string"), provider = Some(defaultProvider) ) @@ -959,7 +959,7 @@ abstract class ExternalCatalogSuite extends SparkFunSuite { Map("partCol1" -> "7", "partCol2" -> "8"), CatalogStorageFormat( Some(tempPath.toURI), - None, None, None, false, Map.empty)) + None, None, None, None, false, Map.empty)) catalog.createPartitions("db1", "tbl", Seq(partWithExistingDir), ignoreIfExists = false) tempPath.delete() @@ -968,7 +968,7 @@ abstract class ExternalCatalogSuite extends SparkFunSuite { Map("partCol1" -> "9", "partCol2" -> "10"), CatalogStorageFormat( Some(tempPath.toURI), - None, None, None, false, Map.empty)) + None, None, None, None, false, Map.empty)) catalog.createPartitions("db1", "tbl", Seq(partWithNonExistingDir), ignoreIfExists = false) assert(tempPath.exists()) } @@ -1030,6 +1030,7 @@ abstract class CatalogTestUtils { locationUri = None, inputFormat = Some(tableInputFormat), outputFormat = Some(tableOutputFormat), + serdeName = None, serde = None, compressed = false, properties = Map.empty) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/AlwaysPersistedConfigsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/AlwaysPersistedConfigsSuite.scala index bfadf1eb1885a..ac438320f967b 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/AlwaysPersistedConfigsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/AlwaysPersistedConfigsSuite.scala @@ -158,7 +158,7 @@ class AlwaysPersistedConfigsSuite extends QueryTest with SharedSparkSession { val catalogTable = new CatalogTable( identifier = TableIdentifier(testViewName), tableType = CatalogTableType.VIEW, - storage = CatalogStorageFormat(None, None, None, None, false, Map.empty), + storage = CatalogStorageFormat(None, None, None, None, None, false, Map.empty), schema = new StructType(), properties = Map.empty[String, String] ) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DDLSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DDLSuite.scala index 42410a6cca52b..46cf79b60b25a 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DDLSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DDLSuite.scala @@ -317,7 +317,7 @@ trait DDLSuiteBase extends SQLTestUtils { spec: TablePartitionSpec, tableName: TableIdentifier): Unit = { val part = CatalogTablePartition( - spec, CatalogStorageFormat(None, None, None, None, false, Map())) + spec, CatalogStorageFormat(None, None, None, None, None, false, Map())) catalog.createPartitions(tableName, Seq(part), ignoreIfExists = false) } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/sources/InsertSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/sources/InsertSuite.scala index d92e796455714..4cc8db226b438 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/sources/InsertSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/sources/InsertSuite.scala @@ -944,6 +944,7 @@ class InsertSuite extends DataSourceTest with SharedSparkSession { locationUri = None, inputFormat = None, outputFormat = None, + serdeName = None, serde = None, compressed = false, properties = Map.empty), @@ -972,6 +973,7 @@ class InsertSuite extends DataSourceTest with SharedSparkSession { locationUri = None, inputFormat = None, outputFormat = None, + serdeName = None, serde = None, compressed = false, properties = Map.empty), diff --git a/sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveMetastoreCatalog.scala b/sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveMetastoreCatalog.scala index b0e0cc5a926c8..bfff91b6fc6bf 100644 --- a/sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveMetastoreCatalog.scala +++ b/sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveMetastoreCatalog.scala @@ -177,6 +177,7 @@ private[hive] class HiveMetastoreCatalog(sparkSession: SparkSession) extends Log val options = storage.properties + (ParquetOptions.MERGE_SCHEMA -> SQLConf.get.getConf(HiveUtils.CONVERT_METASTORE_PARQUET_WITH_SCHEMA_MERGING).toString) storage.copy( + serdeName = None, serde = None, properties = options ) @@ -184,11 +185,13 @@ private[hive] class HiveMetastoreCatalog(sparkSession: SparkSession) extends Log val options = storage.properties if (SQLConf.get.getConf(SQLConf.ORC_IMPLEMENTATION) == "native") { storage.copy( + serdeName = None, serde = None, properties = options ) } else { storage.copy( + serdeName = None, serde = None, properties = options ) diff --git a/sql/hive/src/main/scala/org/apache/spark/sql/hive/client/HiveClientImpl.scala b/sql/hive/src/main/scala/org/apache/spark/sql/hive/client/HiveClientImpl.scala index 4404a13c1266a..482d12207b024 100644 --- a/sql/hive/src/main/scala/org/apache/spark/sql/hive/client/HiveClientImpl.scala +++ b/sql/hive/src/main/scala/org/apache/spark/sql/hive/client/HiveClientImpl.scala @@ -557,6 +557,7 @@ private[hive] class HiveClientImpl( outputFormat = Option(h.getTTable.getSd.getOutputFormat).orElse { Option(h.getStorageHandler).map(_.getOutputFormatClass.getName) }, + serdeName = Option(h.getTTable.getSd.getSerdeInfo.getName), serde = Option(h.getSerializationLib), compressed = h.getTTable.getSd.isCompressed, properties = Option(h.getTTable.getSd.getSerdeInfo.getParameters) @@ -1201,6 +1202,7 @@ private[hive] object HiveClientImpl extends Logging { hiveTable.getTTable.getSd.setLocation(loc)} table.storage.inputFormat.map(toInputFormat).foreach(hiveTable.setInputFormatClass) table.storage.outputFormat.map(toOutputFormat).foreach(hiveTable.setOutputFormatClass) + table.storage.serdeName.foreach(hiveTable.getSd.getSerdeInfo.setName) hiveTable.setSerializationLib( table.storage.serde.getOrElse("org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe")) table.storage.properties.foreach { case (k, v) => hiveTable.setSerdeParam(k, v) } @@ -1251,6 +1253,7 @@ private[hive] object HiveClientImpl extends Logging { p.storage.locationUri.map(CatalogUtils.URIToString(_)).foreach(storageDesc.setLocation) p.storage.inputFormat.foreach(storageDesc.setInputFormat) p.storage.outputFormat.foreach(storageDesc.setOutputFormat) + p.storage.serdeName.foreach(serdeInfo.setName) p.storage.serde.foreach(serdeInfo.setSerializationLib) serdeInfo.setParameters(p.storage.properties.asJava) storageDesc.setSerdeInfo(serdeInfo) @@ -1280,6 +1283,7 @@ private[hive] object HiveClientImpl extends Logging { locationUri = Option(CatalogUtils.stringToURI(apiPartition.getSd.getLocation)), inputFormat = Option(apiPartition.getSd.getInputFormat), outputFormat = Option(apiPartition.getSd.getOutputFormat), + serdeName = Option(apiPartition.getSd.getSerdeInfo.getName), serde = Option(apiPartition.getSd.getSerdeInfo.getSerializationLib), compressed = apiPartition.getSd.isCompressed, properties = Option(apiPartition.getSd.getSerdeInfo.getParameters) diff --git a/sql/hive/src/test/scala/org/apache/spark/sql/hive/HiveMetastoreCatalogSuite.scala b/sql/hive/src/test/scala/org/apache/spark/sql/hive/HiveMetastoreCatalogSuite.scala index a7d43ebbef078..671a705b53905 100644 --- a/sql/hive/src/test/scala/org/apache/spark/sql/hive/HiveMetastoreCatalogSuite.scala +++ b/sql/hive/src/test/scala/org/apache/spark/sql/hive/HiveMetastoreCatalogSuite.scala @@ -498,4 +498,19 @@ class DataSourceWithHiveMetastoreCatalogSuite assert(spark.table("t").schema === CatalystSqlParser.parseTableSchema(schema)) } } + + test("SPARK-55645: Read/write Serde Name to/from an external table") { + withTable("t") { + sql("CREATE TABLE t (d1 DECIMAL(10,3), d2 STRING) STORED AS TEXTFILE") + + val hiveTable = + sessionState.catalog.getTableMetadata(TableIdentifier("t", Some("default"))) + val updated = + hiveTable.copy(storage = hiveTable.storage.copy(serdeName = Some("testSerdeName"))) + sessionState.catalog.alterTable(updated) + val tableWithSerdeName = + sessionState.catalog.getTableMetadata(TableIdentifier("t", Some("default"))) + assert(tableWithSerdeName.storage.serdeName === Some("testSerdeName")) + } + } } diff --git a/sql/hive/src/test/scala/org/apache/spark/sql/hive/HiveSchemaInferenceSuite.scala b/sql/hive/src/test/scala/org/apache/spark/sql/hive/HiveSchemaInferenceSuite.scala index 5e521565383ce..089b131d3c272 100644 --- a/sql/hive/src/test/scala/org/apache/spark/sql/hive/HiveSchemaInferenceSuite.scala +++ b/sql/hive/src/test/scala/org/apache/spark/sql/hive/HiveSchemaInferenceSuite.scala @@ -107,6 +107,7 @@ class HiveSchemaInferenceSuite locationUri = Option(dir.toURI), inputFormat = serde.inputFormat, outputFormat = serde.outputFormat, + serdeName = None, serde = serde.serde, compressed = false, properties = Map("serialization.format" -> "1")), diff --git a/sql/hive/src/test/scala/org/apache/spark/sql/hive/MetastoreDataSourcesSuite.scala b/sql/hive/src/test/scala/org/apache/spark/sql/hive/MetastoreDataSourcesSuite.scala index 772db8dff615f..b0afd8c2376d3 100644 --- a/sql/hive/src/test/scala/org/apache/spark/sql/hive/MetastoreDataSourcesSuite.scala +++ b/sql/hive/src/test/scala/org/apache/spark/sql/hive/MetastoreDataSourcesSuite.scala @@ -756,6 +756,7 @@ class MetastoreDataSourcesSuite extends QueryTest locationUri = None, inputFormat = None, outputFormat = None, + serdeName = None, serde = None, compressed = false, properties = Map( diff --git a/sql/hive/src/test/scala/org/apache/spark/sql/hive/client/HiveClientSuite.scala b/sql/hive/src/test/scala/org/apache/spark/sql/hive/client/HiveClientSuite.scala index 7db9632c87b9d..623410c4e69df 100644 --- a/sql/hive/src/test/scala/org/apache/spark/sql/hive/client/HiveClientSuite.scala +++ b/sql/hive/src/test/scala/org/apache/spark/sql/hive/client/HiveClientSuite.scala @@ -82,6 +82,7 @@ class HiveClientSuite(version: String) extends HiveVersionSuite(version) { locationUri = None, inputFormat = Some(classOf[TextInputFormat].getName), outputFormat = Some(classOf[HiveIgnoreKeyTextOutputFormat[_, _]].getName), + serdeName = None, serde = Some(classOf[LazySimpleSerDe].getName), compressed = false, properties = Map.empty @@ -369,6 +370,7 @@ class HiveClientSuite(version: String) extends HiveVersionSuite(version) { locationUri = None, inputFormat = None, outputFormat = None, + serdeName = None, serde = None, compressed = false, properties = Map.empty) @@ -383,6 +385,7 @@ class HiveClientSuite(version: String) extends HiveVersionSuite(version) { locationUri = None, inputFormat = Some(classOf[TextInputFormat].getName), outputFormat = Some(classOf[HiveIgnoreKeyTextOutputFormat[_, _]].getName), + serdeName = None, serde = Some(classOf[LazySimpleSerDe].getName), compressed = false, properties = Map.empty diff --git a/sql/hive/src/test/scala/org/apache/spark/sql/hive/client/HivePartitionFilteringSuite.scala b/sql/hive/src/test/scala/org/apache/spark/sql/hive/client/HivePartitionFilteringSuite.scala index fae01d6cbc451..ddcd2aea06dff 100644 --- a/sql/hive/src/test/scala/org/apache/spark/sql/hive/client/HivePartitionFilteringSuite.scala +++ b/sql/hive/src/test/scala/org/apache/spark/sql/hive/client/HivePartitionFilteringSuite.scala @@ -63,6 +63,7 @@ class HivePartitionFilteringSuite(version: String) locationUri = None, inputFormat = Some(classOf[TextInputFormat].getName), outputFormat = Some(classOf[HiveIgnoreKeyTextOutputFormat[_, _]].getName), + serdeName = None, serde = Some(classOf[LazySimpleSerDe].getName()), compressed = false, properties = Map.empty diff --git a/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveDDLSuite.scala b/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveDDLSuite.scala index 43f15a12cad19..a73736fbde7ae 100644 --- a/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveDDLSuite.scala +++ b/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveDDLSuite.scala @@ -84,6 +84,7 @@ class HiveDDLSuite locationUri = Some(catalog.defaultTablePath(name)), inputFormat = serde.get.inputFormat, outputFormat = serde.get.outputFormat, + serdeName = None, serde = serde.get.serde, compressed = false, properties = Map.empty) @@ -92,6 +93,7 @@ class HiveDDLSuite locationUri = Some(catalog.defaultTablePath(name)), inputFormat = Some("org.apache.hadoop.mapred.SequenceFileInputFormat"), outputFormat = Some("org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat"), + serdeName = None, serde = Some("org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe"), compressed = false, properties = Map("serialization.format" -> "1")) From e52dfc5026d3ddfbbe738cd070750693d3ccd3f7 Mon Sep 17 00:00:00 2001 From: Ruifeng Zheng Date: Thu, 26 Feb 2026 22:15:36 -0800 Subject: [PATCH 076/130] [MINOR][DOCS] Document how to run a specified benchmark ### What changes were proposed in this pull request? Document how to run a specified benchmark ### Why are the changes needed? to address https://github.com/apache/spark/pull/54530#issuecomment-3970758583 ### Does this PR introduce _any_ user-facing change? No, dev-only ### How was this patch tested? CI ### Was this patch authored or co-authored using generative AI tooling? No Closes #54536 from zhengruifeng/doc_how_separate_benchmark. Authored-by: Ruifeng Zheng Signed-off-by: Dongjoon Hyun --- python/benchmarks/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/benchmarks/README.md b/python/benchmarks/README.md index 0a6013791ccf8..c9bab2ee4ed30 100644 --- a/python/benchmarks/README.md +++ b/python/benchmarks/README.md @@ -24,6 +24,13 @@ cd python/benchmarks asv run --python=same --quick ``` +You can also specify the test class to run: + +```bash +cd python/benchmarks +asv run --python=same --quick -b 'bench_arrow.LongArrowToPandasBenchmark' +``` + ### Full run against a commit Run benchmarks in an isolated virtualenv (builds pyspark from source): From 61c87b283e2787cd7ea2d027953be9abb04fc3cb Mon Sep 17 00:00:00 2001 From: Ruifeng Zheng Date: Thu, 26 Feb 2026 22:18:28 -0800 Subject: [PATCH 077/130] [SPARK-55743][PYTHON][TESTS] Add `python/benchmarks` in python linter ### What changes were proposed in this pull request? Add `python/benchmarks` in python linter ### Why are the changes needed? to make python linter works in `python/benchmarks` ### Does this PR introduce _any_ user-facing change? no, dev-only ### How was this patch tested? ci and manually run `dev/reformat-python` ### Was this patch authored or co-authored using generative AI tooling? no Closes #54535 from zhengruifeng/reformat_benchmark. Authored-by: Ruifeng Zheng Signed-off-by: Dongjoon Hyun --- dev/lint-python | 2 +- dev/reformat-python | 2 +- python/benchmarks/bench_arrow.py | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/dev/lint-python b/dev/lint-python index 1ed042b66dfa2..a4ee6752d575c 100755 --- a/dev/lint-python +++ b/dev/lint-python @@ -330,7 +330,7 @@ function black_test { fi echo "starting black test..." - BLACK_REPORT=$( ($BLACK_BUILD --check python/pyspark dev python/packaging) 2>&1) + BLACK_REPORT=$( ($BLACK_BUILD --check python/pyspark dev python/packaging python/benchmarks) 2>&1) BLACK_STATUS=$? if [ "$BLACK_STATUS" -ne 0 ]; then diff --git a/dev/reformat-python b/dev/reformat-python index 4bc3a733ec2b7..19f0ffa74cc73 100755 --- a/dev/reformat-python +++ b/dev/reformat-python @@ -29,4 +29,4 @@ if [ $? -ne 0 ]; then exit 1 fi -$BLACK_BUILD python/pyspark dev python/packaging +$BLACK_BUILD python/pyspark dev python/packaging python/benchmarks diff --git a/python/benchmarks/bench_arrow.py b/python/benchmarks/bench_arrow.py index 7ace66f229654..29a95dbcc98b5 100644 --- a/python/benchmarks/bench_arrow.py +++ b/python/benchmarks/bench_arrow.py @@ -35,9 +35,7 @@ class ArrowToPandasBenchmark: def setup(self, n_rows, types_mapper): self.int_array = pa.array(np.random.randint(0, 1000, n_rows)) - self.int_array_with_nulls = pa.array( - [i if i % 10 != 0 else None for i in range(n_rows)] - ) + self.int_array_with_nulls = pa.array([i if i % 10 != 0 else None for i in range(n_rows)]) self.types_mapper = pd.ArrowDtype if types_mapper == "arrow_dtype" else None def time_int_to_pandas(self, n_rows, types_mapper): @@ -95,7 +93,7 @@ def setup(self, n_rows, method): self.long_array_with_nulls = pa.array( [i if i % 10 != 0 else None for i in range(n_rows - 1)] + [9223372036854775707], type=pa.int64(), - ) + ) # check 3 different ways to convert nullable longs to nullable extension type def run_long_with_nulls_to_pandas_ext(self, n_rows, method): From 3f64bcaee77b3ebabaadb7852ebb0fb17fb14d26 Mon Sep 17 00:00:00 2001 From: Ruifeng Zheng Date: Fri, 27 Feb 2026 15:23:23 +0800 Subject: [PATCH 078/130] [SPARK-55736][PYTHON][TESTS] Add tests for mismatched batch sizes in scalar iter UDFs ### What changes were proposed in this pull request? Add tests for mismatched batch sizes in scalar iter UDFs ### Why are the changes needed? From the API reference https://apache.github.io/spark/api/python/reference/pyspark.sql/api/pyspark.sql.functions.pandas_udf.html?highlight=pandas_udf#pyspark.sql.functions.pandas_udf > The length of the entire output from the function should be the same length of the entire input; therefore, it can prefetch the data from the input iterator as long as the lengths are the same. The scalar iter UDFs don't require the output batches have the same sizes of input batches. While existing examples and tests are all for this case. This PR is to guard the case of mismatched batch sizes, with a test 200 input batches -> single output batch ### Does this PR introduce _any_ user-facing change? No, test-only ### How was this patch tested? CI ### Was this patch authored or co-authored using generative AI tooling? No Closes #54531 from zhengruifeng/test_iter_udf. Authored-by: Ruifeng Zheng Signed-off-by: Ruifeng Zheng --- .../sql/tests/arrow/test_arrow_udf_scalar.py | 21 +++++++++++++++++++ .../tests/pandas/test_pandas_udf_scalar.py | 19 +++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/python/pyspark/sql/tests/arrow/test_arrow_udf_scalar.py b/python/pyspark/sql/tests/arrow/test_arrow_udf_scalar.py index 88ea7ad080192..061a80908f08a 100644 --- a/python/pyspark/sql/tests/arrow/test_arrow_udf_scalar.py +++ b/python/pyspark/sql/tests/arrow/test_arrow_udf_scalar.py @@ -1264,6 +1264,27 @@ def my_scalar_iter_arrow_udf(it): ], ) + def test_scalar_iter_arrow_udf_with_single_output_batch(self): + import pyarrow as pa + + @arrow_udf("long", ArrowUDFType.SCALAR_ITER) + def return_one(iterator): + rows = 0 + batches = 0 + for s in iterator: + rows += len(s) + batches += 1 + + assert rows == 1000, rows + assert batches == 200, batches + yield pa.array([1] * rows) + + with self.sql_conf({"spark.sql.execution.arrow.maxRecordsPerBatch": 5}): + df = self.spark.range(0, 1000, 1, 1) + expected = [Row(one=1) for i in range(1000)] + result = df.select(return_one("id").alias("one")).collect() + self.assertEqual(expected, result) + class ScalarArrowUDFTests(ScalarArrowUDFTestsMixin, ReusedSQLTestCase): @classmethod diff --git a/python/pyspark/sql/tests/pandas/test_pandas_udf_scalar.py b/python/pyspark/sql/tests/pandas/test_pandas_udf_scalar.py index ad3a3bea3e53d..2aecb5efe7f89 100644 --- a/python/pyspark/sql/tests/pandas/test_pandas_udf_scalar.py +++ b/python/pyspark/sql/tests/pandas/test_pandas_udf_scalar.py @@ -2044,6 +2044,25 @@ def plus_two(iterator): result = df.select(plus_two("id").alias("result")).collect() self.assertEqual(expected, result) + def test_scalar_iter_pandas_udf_with_single_output_batch(self): + @pandas_udf("long", PandasUDFType.SCALAR_ITER) + def return_one(iterator): + rows = 0 + batches = 0 + for s in iterator: + rows += len(s) + batches += 1 + + assert rows == 1000, rows + assert batches == 200, batches + yield pd.Series([1] * rows) + + with self.sql_conf({"spark.sql.execution.arrow.maxRecordsPerBatch": 5}): + df = self.spark.range(0, 1000, 1, 1) + expected = [Row(one=1) for i in range(1000)] + result = df.select(return_one("id").alias("one")).collect() + self.assertEqual(expected, result) + class ScalarPandasUDFTests(ScalarPandasUDFTestsMixin, ReusedSQLTestCase): @classmethod From b9ad07342410504226e37a934ecf8b8c3561846e Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Fri, 27 Feb 2026 16:34:14 +0800 Subject: [PATCH 079/130] [MINOR][INFRA] Update outdated comment for GHA runner ### What changes were proposed in this pull request? GHA runner has limited 2C/7G, now limits 4C/16G, for public repo. https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-runners-for-public-repositories ### Why are the changes needed? Update outdated comments. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Review. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54541 from pan3793/minor-gha. Authored-by: Cheng Pan Signed-off-by: Cheng Pan --- .github/workflows/build_and_test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 4861d49739904..12a2d78639cd9 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -1444,7 +1444,8 @@ jobs: uses: medyagh/setup-minikube@v0.0.21 with: kubernetes-version: "1.35.0" - # Github Action limit cpu:2, memory: 6947MB, limit to 2U6G for better resource statistic + # GitHub Actions limit 4C/16G, limit to 2C/6G for better resource statistic + # https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-runners-for-public-repositories cpus: 2 memory: 6144m - name: Print K8S pods and nodes info From 3b06a6580a3484c71444b2229c1292c2b800eb20 Mon Sep 17 00:00:00 2001 From: Szehon Ho Date: Fri, 27 Feb 2026 16:49:33 +0800 Subject: [PATCH 080/130] [SPARK-55696][SQL] Add explicit error to Encoders.bean for interface class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? Add explicit error message to Encoders.bean against interfaces ### Why are the changes needed? For bean Encoders, the de-serializer uses the constructor inferred from the bean Encoder. ie, we get the bytes back, the Dataset deserialization will use the Encoder's interface class to try to construct , and fail. Code ref: https://github.com/apache/spark/blob/b3703755d80585297367d539de9fa8c5783b1c6b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/DeserializerBuildHelper.scala#L482 ### Does this PR introduce _any_ user-facing change? No, it already fails today with another message: ``` java.lang.IllegalStateException: found an unhandled type: null       at org.apache.commons.lang3.reflect.TypeUtils.getTypeArguments(TypeUtils.java:915)       at org.apache.commons.lang3.reflect.TypeUtils.getTypeArguments(TypeUtils.java:791)       at org.apache.commons.lang3.reflect.TypeUtils.getTypeArguments(TypeUtils.java:886)       at org.apache.commons.lang3.reflect.TypeUtils.getTypeArguments(TypeUtils.java:873)       at org.apache.spark.sql.catalyst.JavaTypeInference$.encoderFor(JavaTypeInference.scala:159)       at org.apache.spark.sql.catalyst.JavaTypeInference$.encoderFor(JavaTypeInference.scala:63)       at org.apache.spark.sql.catalyst.JavaTypeInference$.encoderFor(JavaTypeInference.scala:56)       at org.apache.spark.sql.Encoders$.bean(Encoders.scala:211)       at org.apache.spark.sql.Encoders.bean(Encoders.scala) ``` it will now fail more explicitly. ### How was this patch tested? Added unit test in JavaDatasetSuite ### Was this patch authored or co-authored using generative AI tooling? Yes, cursor Closes #54494 from szehon-ho/encoder_interface. Authored-by: Szehon Ho Signed-off-by: Cheng Pan --- .../resources/error/error-conditions.json | 6 + .../scala/org/apache/spark/sql/Encoders.scala | 2 +- .../sql/catalyst/JavaTypeInference.scala | 8 ++ .../apache/spark/sql/JavaDatasetSuite.java | 115 ++++++++++++++++++ 4 files changed, 130 insertions(+), 1 deletion(-) diff --git a/common/utils/src/main/resources/error/error-conditions.json b/common/utils/src/main/resources/error/error-conditions.json index 94111b8e9ee0f..52a21e43ea9eb 100644 --- a/common/utils/src/main/resources/error/error-conditions.json +++ b/common/utils/src/main/resources/error/error-conditions.json @@ -206,6 +206,12 @@ ], "sqlState" : "42K03" }, + "BEAN_ENCODER_INTERFACE_NOT_SUPPORTED" : { + "message" : [ + "Bean encoder does not support interface type ." + ], + "sqlState" : "0A000" + }, "BINARY_ARITHMETIC_OVERFLOW" : { "message" : [ " caused overflow. Use to ignore overflow problem and return NULL." diff --git a/sql/api/src/main/scala/org/apache/spark/sql/Encoders.scala b/sql/api/src/main/scala/org/apache/spark/sql/Encoders.scala index 7e698e58321ee..72cd1190ba40c 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/Encoders.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/Encoders.scala @@ -195,7 +195,7 @@ object Encoders { /** * Creates an encoder for Java Bean of type T. * - * T must be publicly accessible. + * T must be a concrete class (not an interface), and must be publicly accessible. * * supported types for java bean field: * - primitive types: boolean, int, double, etc. diff --git a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/JavaTypeInference.scala b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/JavaTypeInference.scala index 91947cf416fb6..c7d3e4a47c7f3 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/JavaTypeInference.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/JavaTypeInference.scala @@ -26,6 +26,7 @@ import scala.reflect.ClassTag import org.apache.commons.lang3.reflect.{TypeUtils => JavaTypeUtils} +import org.apache.spark.SparkUnsupportedOperationException import org.apache.spark.sql.catalyst.encoders.AgnosticEncoder import org.apache.spark.sql.catalyst.encoders.AgnosticEncoders.{ArrayEncoder, BinaryEncoder, BoxedBooleanEncoder, BoxedByteEncoder, BoxedDoubleEncoder, BoxedFloatEncoder, BoxedIntEncoder, BoxedLongEncoder, BoxedShortEncoder, DayTimeIntervalEncoder, DEFAULT_GEOGRAPHY_ENCODER, DEFAULT_GEOMETRY_ENCODER, DEFAULT_JAVA_DECIMAL_ENCODER, EncoderField, IterableEncoder, JavaBeanEncoder, JavaBigIntEncoder, JavaEnumEncoder, LocalDateTimeEncoder, LocalTimeEncoder, MapEncoder, PrimitiveBooleanEncoder, PrimitiveByteEncoder, PrimitiveDoubleEncoder, PrimitiveFloatEncoder, PrimitiveIntEncoder, PrimitiveLongEncoder, PrimitiveShortEncoder, STRICT_DATE_ENCODER, STRICT_INSTANT_ENCODER, STRICT_LOCAL_DATE_ENCODER, STRICT_TIMESTAMP_ENCODER, StringEncoder, UDTEncoder, YearMonthIntervalEncoder} import org.apache.spark.sql.errors.ExecutionErrors @@ -151,6 +152,13 @@ object JavaTypeInference { if (seenTypeSet.contains(c)) { throw ExecutionErrors.cannotHaveCircularReferencesInBeanClassError(c) } + // Encoders for interfaces are not supported because de-serialization uses its + // Deserializer to instantiate the class, which will not work for interfaces. + if (c.isInterface) { + throw new SparkUnsupportedOperationException( + errorClass = "BEAN_ENCODER_INTERFACE_NOT_SUPPORTED", + messageParameters = Map("className" -> c.getName)) + } // TODO: we should only collect properties that have getter and setter. However, some tests // pass in scala case class as java bean class which doesn't have getter and setter. diff --git a/sql/core/src/test/java/test/org/apache/spark/sql/JavaDatasetSuite.java b/sql/core/src/test/java/test/org/apache/spark/sql/JavaDatasetSuite.java index 5b1f98475d51d..62d44e0af8b08 100644 --- a/sql/core/src/test/java/test/org/apache/spark/sql/JavaDatasetSuite.java +++ b/sql/core/src/test/java/test/org/apache/spark/sql/JavaDatasetSuite.java @@ -38,6 +38,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.apache.spark.SparkUnsupportedOperationException; import org.apache.spark.api.java.JavaPairRDD; import org.apache.spark.api.java.JavaSparkContext; import org.apache.spark.api.java.function.*; @@ -1919,6 +1920,120 @@ public void testReadOnlyPropertyBean() { } + /** + * Interface with JavaBean-style getters/setters for testing encoder with interface type. + */ + public interface BeanInterface extends Serializable { + String getValue(); + void setValue(String value); + int getId(); + void setId(int id); + } + + public static class BeanImplA implements BeanInterface { + private String value; + private int id; + + @Override + public String getValue() { return value; } + @Override + public void setValue(String value) { this.value = value; } + @Override + public int getId() { return id; } + @Override + public void setId(int id) { this.id = id; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BeanImplA)) return false; + BeanImplA that = (BeanImplA) o; + return id == that.id && Objects.equals(value, that.value); + } + @Override + public int hashCode() { return Objects.hash(value, id); } + } + + public static class BeanImplB implements BeanInterface { + private String value; + private int id; + + @Override + public String getValue() { return value; } + @Override + public void setValue(String value) { this.value = value; } + @Override + public int getId() { return id; } + @Override + public void setId(int id) { this.id = id; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BeanImplB)) return false; + BeanImplB that = (BeanImplB) o; + return id == that.id && Objects.equals(value, that.value); + } + @Override + public int hashCode() { return Objects.hash(value, id); } + } + + @Test + public void testBeanEncoderRejectsInterface() { + SparkUnsupportedOperationException e = Assertions.assertThrows( + SparkUnsupportedOperationException.class, + () -> Encoders.bean(BeanInterface.class)); + Assertions.assertEquals("BEAN_ENCODER_INTERFACE_NOT_SUPPORTED", e.getCondition()); + Assertions.assertEquals("0A000", e.getSqlState()); + Assertions.assertEquals( + Collections.singletonMap("className", BeanInterface.class.getName()), + e.getMessageParameters()); + } + + @Test + public void testKryoEncoderWithInterface() { + BeanImplA a = new BeanImplA(); + a.setValue("a"); + a.setId(1); + BeanImplB b = new BeanImplB(); + b.setValue("b"); + b.setId(2); + List data = Arrays.asList(a, b); + + Encoder kryoEncoder = Encoders.kryo(BeanInterface.class); + Dataset ds = spark.createDataset(data, kryoEncoder); + List collected = ds.collectAsList(); + Assertions.assertEquals(2, collected.size()); + Assertions.assertEquals("a", collected.get(0).getValue()); + Assertions.assertEquals(1, collected.get(0).getId()); + Assertions.assertEquals("b", collected.get(1).getValue()); + Assertions.assertEquals(2, collected.get(1).getId()); + Assertions.assertInstanceOf(BeanImplA.class, collected.get(0)); + Assertions.assertInstanceOf(BeanImplB.class, collected.get(1)); + } + + @Test + public void testJavaSerializationEncoderWithInterface() { + BeanImplA a = new BeanImplA(); + a.setValue("a"); + a.setId(1); + BeanImplB b = new BeanImplB(); + b.setValue("b"); + b.setId(2); + List data = Arrays.asList(a, b); + + Encoder javaEncoder = Encoders.javaSerialization(BeanInterface.class); + Dataset ds = spark.createDataset(data, javaEncoder); + List collected = ds.collectAsList(); + Assertions.assertEquals(2, collected.size()); + Assertions.assertEquals("a", collected.get(0).getValue()); + Assertions.assertEquals(1, collected.get(0).getId()); + Assertions.assertEquals("b", collected.get(1).getValue()); + Assertions.assertEquals(2, collected.get(1).getId()); + Assertions.assertInstanceOf(BeanImplA.class, collected.get(0)); + Assertions.assertInstanceOf(BeanImplB.class, collected.get(1)); + } + public class CircularReference1Bean implements Serializable { private CircularReference2Bean child; From 72225ddc495311415b7b9c84364cd569601cd53e Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Fri, 27 Feb 2026 20:22:40 +0900 Subject: [PATCH 081/130] [SPARK-55740][TESTS] Fix npm vulnerabilities by `npm audit fix` ### What changes were proposed in this pull request? This pr fix the following npm vulnerabilities by `npm audit fix` in `ui-test/` and `dev/` directory: - ui-test ``` npm audit report # npm audit report minimatch <=3.1.3 || 9.0.0 - 9.0.6 || 10.0.0 - 10.2.2 Severity: high minimatch has a ReDoS via repeated wildcards with non-matching literal in pattern - https://github.com/advisories/GHSA-3ppc-4f35-3m26 minimatch has a ReDoS via repeated wildcards with non-matching literal in pattern - https://github.com/advisories/GHSA-3ppc-4f35-3m26 minimatch has a ReDoS via repeated wildcards with non-matching literal in pattern - https://github.com/advisories/GHSA-3ppc-4f35-3m26 minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adjacent GLOBSTAR segments - https://github.com/advisories/GHSA-7r86-cg39-jmmj minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adjacent GLOBSTAR segments - https://github.com/advisories/GHSA-7r86-cg39-jmmj minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adjacent GLOBSTAR segments - https://github.com/advisories/GHSA-7r86-cg39-jmmj minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regular expressions - https://github.com/advisories/GHSA-23c5-xmqv-rm74 minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regular expressions - https://github.com/advisories/GHSA-23c5-xmqv-rm74 minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regular expressions - https://github.com/advisories/GHSA-23c5-xmqv-rm74 fix available via `npm audit fix` node_modules/jest/reporters/node_modules/minimatch node_modules/jest-config/node_modules/minimatch node_modules/jest-runtime/node_modules/minimatch node_modules/minimatch node_modules/test-exclude/node_modules/minimatch 1 high severity vulnerability To address all issues, run: npm audit fix ``` - dev ``` npm audit report # npm audit report ajv <6.14.0 || >=7.0.0-alpha.0 <8.18.0 Severity: moderate ajv has ReDoS when using `$data` option - https://github.com/advisories/GHSA-2g4f-4pwh-qvx6 ajv has ReDoS when using `$data` option - https://github.com/advisories/GHSA-2g4f-4pwh-qvx6 fix available via `npm audit fix` node_modules/ajv node_modules/table/node_modules/ajv minimatch <=3.1.3 Severity: high minimatch has a ReDoS via repeated wildcards with non-matching literal in pattern - https://github.com/advisories/GHSA-3ppc-4f35-3m26 minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adjacent GLOBSTAR segments - https://github.com/advisories/GHSA-7r86-cg39-jmmj minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regular expressions - https://github.com/advisories/GHSA-23c5-xmqv-rm74 fix available via `npm audit fix` node_modules/minimatch 2 vulnerabilities (1 moderate, 1 high) To address all issues, run: npm audit fix ``` ### Why are the changes needed? Fix npm vulnerabilities in `ui-test/` and `dev/` directory. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? - Pass GitHub Actions ### Was this patch authored or co-authored using generative AI tooling? No Closes #54538 from LuciferYang/SPARK-55740. Authored-by: yangjie01 Signed-off-by: Kousuke Saruta --- dev/package-lock.json | 78 ++++++++++++++++++++++++++------------- ui-test/package-lock.json | 47 +++++++++++++---------- 2 files changed, 81 insertions(+), 44 deletions(-) diff --git a/dev/package-lock.json b/dev/package-lock.json index ff1d72cc117f4..af5c4671f5cba 100644 --- a/dev/package-lock.json +++ b/dev/package-lock.json @@ -148,6 +148,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -165,10 +166,11 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -606,6 +608,23 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -860,10 +879,11 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1137,15 +1157,16 @@ } }, "node_modules/table/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -1345,7 +1366,8 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true + "dev": true, + "peer": true }, "acorn-jsx": { "version": "5.3.2", @@ -1355,9 +1377,9 @@ "requires": {} }, "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -1690,6 +1712,12 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -1890,9 +1918,9 @@ } }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -2089,15 +2117,15 @@ }, "dependencies": { "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" } }, "json-schema-traverse": { diff --git a/ui-test/package-lock.json b/ui-test/package-lock.json index 75981257468d5..6cd2187c92279 100644 --- a/ui-test/package-lock.json +++ b/ui-test/package-lock.json @@ -65,6 +65,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -618,6 +619,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -641,6 +643,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -1008,12 +1011,13 @@ "dev": true }, "node_modules/@jest/reporters/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -1960,6 +1964,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", @@ -3101,12 +3106,13 @@ "dev": true }, "node_modules/jest-config/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -3479,12 +3485,13 @@ "dev": true }, "node_modules/jest-runtime/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -3703,6 +3710,7 @@ "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", @@ -3881,15 +3889,16 @@ } }, "node_modules/minimatch": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.0.tgz", - "integrity": "sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "brace-expansion": "^5.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4665,9 +4674,9 @@ } }, "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { From dc57455589a9f160638ab3526ca359eb84f76d67 Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Fri, 27 Feb 2026 20:27:21 +0800 Subject: [PATCH 082/130] [SPARK-54571][CORE][SQL] Use LZ4 safeDecompressor to mitigate perf regression ### What changes were proposed in this pull request? Previously, lz4-java was upgraded to 1.10.x to address CVEs, - https://github.com/apache/spark/pull/53327 - https://github.com/apache/spark/pull/53347 - https://github.com/apache/spark/pull/53971 while this casues significant performance drop, see the benchmark report at - https://github.com/apache/spark/pull/53453 this PR follows the [suggestion](https://github.com/apache/spark/pull/53290#issuecomment-3607045004) to migrate to safeDecompressor. ### Why are the changes needed? Mitigate performance regression. ### Does this PR introduce _any_ user-facing change? No, except for performance. ### How was this patch tested? GHA for functionality, [benchmark](https://github.com/apache/spark/pull/53453#issuecomment-3645530618) for performance. > TL;DR - my test results show lz4-java 1.10.1 is about 10~15% slower on lz4 compression than 1.8.0, and is about ~5% slower on lz4 decompression even with migrating to suggested safeDecompressor ### Was this patch authored or co-authored using generative AI tooling? No. Closes #53454 from pan3793/SPARK-54571. Lead-authored-by: Cheng Pan Co-authored-by: pan3793 Signed-off-by: Cheng Pan --- .../LZ4TPCDSDataBenchmark-jdk21-results.txt | 4 ++-- core/benchmarks/LZ4TPCDSDataBenchmark-results.txt | 4 ++-- .../scala/org/apache/spark/io/CompressionCodec.scala | 11 +++++------ .../spark/sql/catalyst/plans/logical/Statistics.scala | 7 +++++-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/core/benchmarks/LZ4TPCDSDataBenchmark-jdk21-results.txt b/core/benchmarks/LZ4TPCDSDataBenchmark-jdk21-results.txt index 578f710b1da5e..a066ced506b57 100644 --- a/core/benchmarks/LZ4TPCDSDataBenchmark-jdk21-results.txt +++ b/core/benchmarks/LZ4TPCDSDataBenchmark-jdk21-results.txt @@ -6,12 +6,12 @@ OpenJDK 64-Bit Server VM 21.0.10+7-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor Compression: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------ -Compression 4 times 2612 2624 17 0.0 652960433.5 1.0X +Compression 4 times 2611 2619 11 0.0 652760335.3 1.0X OpenJDK 64-Bit Server VM 21.0.10+7-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor Decompression: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------ -Decompression 4 times 2219 2220 1 0.0 554762743.5 1.0X +Decompression 4 times 896 912 20 0.0 224050201.0 1.0X diff --git a/core/benchmarks/LZ4TPCDSDataBenchmark-results.txt b/core/benchmarks/LZ4TPCDSDataBenchmark-results.txt index 7a5c89955eeb0..8d909dfc7f492 100644 --- a/core/benchmarks/LZ4TPCDSDataBenchmark-results.txt +++ b/core/benchmarks/LZ4TPCDSDataBenchmark-results.txt @@ -6,12 +6,12 @@ OpenJDK 64-Bit Server VM 17.0.18+8-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor Compression: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------ -Compression 4 times 2605 2611 8 0.0 651243236.8 1.0X +Compression 4 times 2602 2609 10 0.0 650438397.0 1.0X OpenJDK 64-Bit Server VM 17.0.18+8-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor Decompression: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------ -Decompression 4 times 2361 2367 10 0.0 590134148.0 1.0X +Decompression 4 times 938 966 33 0.0 234424499.5 1.0X diff --git a/core/src/main/scala/org/apache/spark/io/CompressionCodec.scala b/core/src/main/scala/org/apache/spark/io/CompressionCodec.scala index b81e46667323e..243ee689cb5f2 100644 --- a/core/src/main/scala/org/apache/spark/io/CompressionCodec.scala +++ b/core/src/main/scala/org/apache/spark/io/CompressionCodec.scala @@ -152,12 +152,11 @@ class LZ4CompressionCodec(conf: SparkConf) extends CompressionCodec { } override def compressedInputStream(s: InputStream): InputStream = { - val disableConcatenationOfByteStream = false - new LZ4BlockInputStream( - s, - lz4Factory.fastDecompressor(), - xxHashFactory.newStreamingHash32(defaultSeed).asChecksum, - disableConcatenationOfByteStream) + LZ4BlockInputStream.newBuilder() + .withDecompressor(lz4Factory.safeDecompressor()) + .withChecksum(xxHashFactory.newStreamingHash32(defaultSeed).asChecksum) + .withStopOnEmptyBlock(false) + .build(s) } } diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/logical/Statistics.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/logical/Statistics.scala index a2850a0b179f7..d88bc62d0bc18 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/logical/Statistics.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/logical/Statistics.scala @@ -21,7 +21,7 @@ import java.io.{ByteArrayInputStream, ByteArrayOutputStream, DataInputStream, Da import java.math.{MathContext, RoundingMode} import java.util.Base64 -import net.jpountz.lz4.{LZ4BlockInputStream, LZ4BlockOutputStream} +import net.jpountz.lz4.{LZ4BlockInputStream, LZ4BlockOutputStream, LZ4Factory} import org.apache.spark.sql.catalyst.catalog.CatalogColumnStat import org.apache.spark.sql.catalyst.expressions._ @@ -210,7 +210,10 @@ object HistogramSerializer { final def deserialize(str: String): Histogram = { val bytes = Base64.getDecoder().decode(str) val bis = new ByteArrayInputStream(bytes) - val ins = new DataInputStream(new LZ4BlockInputStream(bis)) + val ins = new DataInputStream( + LZ4BlockInputStream.newBuilder() + .withDecompressor(LZ4Factory.fastestInstance().safeDecompressor()) + .build(bis)) val height = ins.readDouble() val numBins = ins.readInt() From a83eec8235cc9241687b483524927f545dc84596 Mon Sep 17 00:00:00 2001 From: Anastasiia Terenteva Date: Fri, 27 Feb 2026 10:57:22 -0400 Subject: [PATCH 083/130] [SPARK-55691][CONNECT] GetStatus client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? Client-side implementation of the GetStatus API: - Add client methods for requesting operation statuses. - GetStatus API is designed to support other request types that operation statuses in future. For those types, new methods will have to be created. This is a tradeoff between convenient client methods which encapsulate the most of the request building and flexibility. - Mark the client methods as Experimental and underscored for now, until enough confidence in the API stability is built. - Add client tests with mocked service. - Add E2E tests with real operation lifecycles. ### Why are the changes needed? GetStatus API allows to monitor status of executions in a session, which is particularly useful in multithreaded clients. ### Does this PR introduce _any_ user-facing change? Yes. It's a new Spark Connect API. ### How was this patch tested? - Add client tests with mocked service. - Add E2E tests with real operation lifecycles, which also test server-side changes. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: Claude 4.6 Opus High Closes #54520 from terana/get-status-client. Authored-by: Anastasiia Terenteva Signed-off-by: Herman van Hövell --- python/pyspark/sql/connect/client/core.py | 53 +++++ .../sql/tests/connect/client/test_client.py | 174 +++++++++++++- .../client/SparkConnectClientSuite.scala | 164 +++++++++++++ .../CustomSparkConnectBlockingStub.scala | 13 ++ .../connect/client/SparkConnectClient.scala | 39 +++- .../sql/connect/SparkConnectServerTest.scala | 33 ++- .../service/GetStatusHandlerE2ESuite.scala | 216 ++++++++++++++++++ 7 files changed, 673 insertions(+), 19 deletions(-) create mode 100644 sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/GetStatusHandlerE2ESuite.scala diff --git a/python/pyspark/sql/connect/client/core.py b/python/pyspark/sql/connect/client/core.py index f28d97e7472e2..aa060df24e410 100644 --- a/python/pyspark/sql/connect/client/core.py +++ b/python/pyspark/sql/connect/client/core.py @@ -1930,6 +1930,58 @@ def release_session(self) -> None: except Exception as error: self._handle_error(error) + def _get_operation_statuses( + self, + operation_ids: Optional[List[str]] = None, + operation_extensions: Optional[List[any_pb2.Any]] = None, + request_extensions: Optional[List[any_pb2.Any]] = None, + ) -> "pb2.GetStatusResponse": + """ + Get status of operations in the session. + + Parameters + ---------- + operation_ids : list of str, optional + List of operation IDs to get status for. + If None or empty, returns status of all operations in the session. + operation_extensions : list of google.protobuf.any_pb2.Any, optional + Per-operation extension messages to include in the OperationStatusRequest to request + additional per-operation information. + request_extensions : list of google.protobuf.any_pb2.Any, optional + Request-level extension messages to include in the GetStatusRequest. + + Returns + ------- + pb2.GetStatusResponse + The full GetStatusResponse, including operation_statuses and any extensions. + """ + req = pb2.GetStatusRequest() + req.session_id = self._session_id + req.client_type = self._builder.userAgent + if self._user_id: + req.user_context.user_id = self._user_id + if self._server_session_id: + req.client_observed_server_side_session_id = self._server_session_id + + req.operation_status.SetInParent() + + if operation_ids: + req.operation_status.operation_ids.extend(operation_ids) + if operation_extensions: + req.operation_status.extensions.extend(operation_extensions) + if request_extensions: + req.extensions.extend(request_extensions) + + try: + for attempt in self._retrying(): + with attempt: + resp = self._stub.GetStatus(req, metadata=self._builder.metadata()) + self._verify_response_integrity(resp) + return resp + raise SparkConnectException("Invalid state during retry exception handling.") + except Exception as error: + self._handle_error(error) + def add_tag(self, tag: str) -> None: self._throw_if_invalid_tag(tag) if not hasattr(self.thread_local, "tags"): @@ -2169,6 +2221,7 @@ def _verify_response_integrity( pb2.AnalyzePlanResponse, pb2.FetchErrorDetailsResponse, pb2.ReleaseSessionResponse, + pb2.GetStatusResponse, ], ) -> None: """ diff --git a/python/pyspark/sql/tests/connect/client/test_client.py b/python/pyspark/sql/tests/connect/client/test_client.py index 8daf82ad3f373..55faff5e9ed32 100644 --- a/python/pyspark/sql/tests/connect/client/test_client.py +++ b/python/pyspark/sql/tests/connect/client/test_client.py @@ -134,10 +134,25 @@ class MockService: req: Optional[proto.ExecutePlanRequest] - def __init__(self, session_id: str): + OperationStatus = proto.GetStatusResponse.OperationStatus + DEFAULT_OPERATION_STATUSES = [ + OperationStatus( + operation_id="default-op-1", + state=OperationStatus.OperationState.OPERATION_STATE_SUCCEEDED, + ), + OperationStatus( + operation_id="default-op-2", + state=OperationStatus.OperationState.OPERATION_STATE_RUNNING, + ), + ] + + def __init__(self, session_id: str, operation_statuses=None): self._session_id = session_id self.req = None self.client_user_context_extensions = [] + if operation_statuses is None: + operation_statuses = self.DEFAULT_OPERATION_STATUSES + self._operation_statuses = {s.operation_id: s for s in operation_statuses} def ExecutePlan(self, req: proto.ExecutePlanRequest, metadata): self.req = req @@ -191,6 +206,45 @@ def AnalyzePlan(self, req: proto.AnalyzePlanRequest, metadata): resp.semantic_hash.result = 12345 return resp + def GetStatus(self, req: proto.GetStatusRequest, metadata): + self.req = req + self.client_user_context_extensions = list(req.user_context.extensions) + self.received_custom_server_session_id = req.client_observed_server_side_session_id + resp = proto.GetStatusResponse(session_id=self._session_id) + + # Echo top-level request extensions back in the response + if req.extensions: + resp.extensions.extend(req.extensions) + + if not req.HasField("operation_status"): + return resp + + # Collect operation-status-level extensions from the request to echo back + op_status_extensions = list(req.operation_status.extensions) + + requested_ids = list(req.operation_status.operation_ids) + if len(requested_ids) == 0: + # Empty list — return all statuses + resp.operation_statuses.extend(self._operation_statuses.values()) + return resp + + OperationStatus = proto.GetStatusResponse.OperationStatus + for op_id in requested_ids: + status = self._operation_statuses.get(op_id) + if status is not None: + op_status = OperationStatus( + operation_id=status.operation_id, + state=status.state, + ) + else: + op_status = OperationStatus( + operation_id=op_id, + state=OperationStatus.OperationState.OPERATION_STATE_UNKNOWN, + ) + op_status.extensions.extend(op_status_extensions) + resp.operation_statuses.append(op_status) + return resp + # The _cleanup_ml_cache invocation will hang in this test (no valid spark cluster) # and it blocks the test process exiting because it is registered as the atexit handler # in `SparkConnectClient` constructor. To bypass the issue, patch the method in the test. @@ -396,6 +450,124 @@ def test_custom_operation_id(self): for resp in client._stub.ExecutePlan(req, metadata=None): assert resp.operation_id == "10a4c38e-7e87-40ee-9d6f-60ff0751e63b" + def test_get_operations_statuses_all(self): + """Test get_operations_statuses returns all operation statuses when no IDs specified.""" + OperationStatus = proto.GetStatusResponse.OperationStatus + client = SparkConnectClient("sc://foo/;token=bar", use_reattachable_execute=False) + mock = MockService(client._session_id) + client._stub = mock + + resp = client._get_operation_statuses() + result = list(resp.operation_statuses) + self.assertEqual(len(result), 2) + status_map = {s.operation_id: s.state for s in result} + self.assertEqual( + status_map["default-op-1"], + OperationStatus.OperationState.OPERATION_STATE_SUCCEEDED, + ) + self.assertEqual( + status_map["default-op-2"], + OperationStatus.OperationState.OPERATION_STATE_RUNNING, + ) + + def test_get_operations_statuses_specific_ids(self): + """Test get_operations_statuses filters by specific operation IDs.""" + OperationStatus = proto.GetStatusResponse.OperationStatus + client = SparkConnectClient("sc://foo/;token=bar", use_reattachable_execute=False) + mock = MockService(client._session_id) + client._stub = mock + + resp = client._get_operation_statuses(operation_ids=["default-op-1", "unknown-op"]) + result = list(resp.operation_statuses) + self.assertEqual(len(result), 2) + status_map = {s.operation_id: s.state for s in result} + self.assertEqual( + status_map["default-op-1"], + OperationStatus.OperationState.OPERATION_STATE_SUCCEEDED, + ) + self.assertEqual( + status_map["unknown-op"], + OperationStatus.OperationState.OPERATION_STATE_UNKNOWN, + ) + # Verify the request included the operation IDs + self.assertEqual( + set(mock.req.operation_status.operation_ids), {"default-op-1", "unknown-op"} + ) + + def test_get_operations_statuses_empty(self): + """Test get_operations_statuses returns empty list when no operations exist.""" + client = SparkConnectClient("sc://foo/;token=bar", use_reattachable_execute=False) + mock = MockService(client._session_id, operation_statuses=[]) + client._stub = mock + + resp = client._get_operation_statuses() + self.assertEqual(len(list(resp.operation_statuses)), 0) + + def test_get_operations_statuses_with_operation_extensions(self): + """Test get_operations_statuses passes operation-level extensions and echoes them back per operation.""" + from google.protobuf import any_pb2, wrappers_pb2 + + client = SparkConnectClient("sc://foo/;token=bar", use_reattachable_execute=False) + mock = MockService(client._session_id) + client._stub = mock + + op_ext = any_pb2.Any() + op_ext.Pack(wrappers_pb2.StringValue(value="op_extension")) + + resp = client._get_operation_statuses( + operation_ids=["default-op-1", "default-op-2"], + operation_extensions=[op_ext], + ) + result = list(resp.operation_statuses) + self.assertEqual(len(result), 2) + self.assertEqual({s.operation_id for s in result}, {"default-op-1", "default-op-2"}) + + # Verify operation-level extensions were included in the request + self.assertEqual(len(mock.req.operation_status.extensions), 1) + unpacked = wrappers_pb2.StringValue() + mock.req.operation_status.extensions[0].Unpack(unpacked) + self.assertEqual(unpacked.value, "op_extension") + + # Verify operation-level extensions were echoed back per operation + for op_status in result: + self.assertEqual(len(op_status.extensions), 1) + echoed = wrappers_pb2.StringValue() + op_status.extensions[0].Unpack(echoed) + self.assertEqual(echoed.value, "op_extension") + + def test_get_operations_statuses_with_request_extensions(self): + """Test _get_operation_statuses sends request-level extensions and echoes them back.""" + from google.protobuf import any_pb2, wrappers_pb2 + + client = SparkConnectClient("sc://foo/;token=bar", use_reattachable_execute=False) + mock = MockService(client._session_id) + client._stub = mock + + req_ext = any_pb2.Any() + req_ext.Pack(wrappers_pb2.StringValue(value="request_extension")) + + resp = client._get_operation_statuses( + operation_ids=["default-op-1"], + request_extensions=[req_ext], + ) + + # Verify the operation status is returned + result = list(resp.operation_statuses) + self.assertEqual(len(result), 1) + self.assertEqual(result[0].operation_id, "default-op-1") + + # Verify request-level extensions were included in the request + self.assertEqual(len(mock.req.extensions), 1) + unpacked = wrappers_pb2.StringValue() + mock.req.extensions[0].Unpack(unpacked) + self.assertEqual(unpacked.value, "request_extension") + + # Verify request-level extensions were echoed back in the response + self.assertEqual(len(resp.extensions), 1) + resp_echoed = wrappers_pb2.StringValue() + resp.extensions[0].Unpack(resp_echoed) + self.assertEqual(resp_echoed.value, "request_extension") + @unittest.skipIf(not should_test_connect, connect_requirement_message) class SparkConnectClientReattachTestCase(unittest.TestCase): diff --git a/sql/connect/client/jvm/src/test/scala/org/apache/spark/sql/connect/client/SparkConnectClientSuite.scala b/sql/connect/client/jvm/src/test/scala/org/apache/spark/sql/connect/client/SparkConnectClientSuite.scala index 1cfc2d3eb09fc..e833657984dcb 100644 --- a/sql/connect/client/jvm/src/test/scala/org/apache/spark/sql/connect/client/SparkConnectClientSuite.scala +++ b/sql/connect/client/jvm/src/test/scala/org/apache/spark/sql/connect/client/SparkConnectClientSuite.scala @@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit import scala.collection.mutable import scala.jdk.CollectionConverters._ +import com.google.protobuf.{Any => PAny, StringValue} import io.grpc.{CallOptions, Channel, ClientCall, ClientInterceptor, Metadata, MethodDescriptor, Server, ServerCall, ServerCallHandler, ServerInterceptor, Status, StatusRuntimeException} import io.grpc.netty.NettyServerBuilder import io.grpc.stub.StreamObserver @@ -548,6 +549,114 @@ class SparkConnectClientSuite extends ConnectFunSuite { observer.onCompleted() } + test("getOperationStatuses returns operation statuses for requested IDs") { + startDummyServer(0) + client = SparkConnectClient + .builder() + .connectionString(s"sc://localhost:${server.getPort}") + .build() + + val response = + client.getOperationStatuses(Seq("default-op-1", "unknown-op")) + val statuses = response.getOperationStatusesList.asScala.toSeq + assert(statuses.size == 2) + assert(statuses.map(_.getOperationId).toSet == Set("default-op-1", "unknown-op")) + + val statusMap = statuses.map(s => s.getOperationId -> s.getState).toMap + assert( + statusMap("default-op-1") == + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_SUCCEEDED) + assert( + statusMap("unknown-op") == + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_UNKNOWN) + } + + test("getOperationStatuses with no IDs returns all operations from server") { + startDummyServer(0) + client = SparkConnectClient + .builder() + .connectionString(s"sc://localhost:${server.getPort}") + .build() + + val response = client.getOperationStatuses() + val statuses = response.getOperationStatusesList.asScala.toSeq + assert(statuses.size == 2) + assert(statuses.map(_.getOperationId).toSet == Set("default-op-1", "default-op-2")) + + val statusMap = statuses.map(s => s.getOperationId -> s.getState).toMap + assert( + statusMap("default-op-1") == + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_SUCCEEDED) + assert( + statusMap("default-op-2") == + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_RUNNING) + } + + test("getOperationStatuses sends extensions and returns them per operation") { + startDummyServer(0) + client = SparkConnectClient + .builder() + .connectionString(s"sc://localhost:${server.getPort}") + .build() + + val extension = PAny.pack(StringValue.of("custom_extension")) + + val response = client.getOperationStatuses( + operationIds = Seq("default-op-1", "default-op-2"), + operationExtensions = Seq(extension)) + + // Verify operation statuses are returned + val statuses = response.getOperationStatusesList.asScala.toSeq + assert(statuses.size == 2) + + val statusMap = statuses.map(s => s.getOperationId -> s).toMap + assert( + statusMap("default-op-1").getState == + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_SUCCEEDED) + assert( + statusMap("default-op-2").getState == + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_RUNNING) + + // Verify that extensions are echoed back per operation + statuses.foreach { status => + val opExtensions = status.getExtensionsList.asScala.toSeq + assert(opExtensions.size == 1) + assert(opExtensions.head.is(classOf[StringValue])) + assert( + opExtensions.head + .unpack(classOf[StringValue]) + .getValue == "custom_extension") + } + } + + test("getOperationStatuses sends request-level extensions and echoes them in the response") { + startDummyServer(0) + client = SparkConnectClient + .builder() + .connectionString(s"sc://localhost:${server.getPort}") + .build() + + val reqExtension = PAny.pack(StringValue.of("request_extension")) + + val response = client.getOperationStatuses( + operationIds = Seq("default-op-1"), + requestExtensions = Seq(reqExtension)) + + // Verify the operation status is returned + val statuses = response.getOperationStatusesList.asScala.toSeq + assert(statuses.size == 1) + assert(statuses.head.getOperationId == "default-op-1") + + // Verify request-level extensions were echoed back in the response + val responseExtensions = response.getExtensionsList.asScala.toSeq + assert(responseExtensions.size == 1) + assert(responseExtensions.head.is(classOf[StringValue])) + assert( + responseExtensions.head + .unpack(classOf[StringValue]) + .getValue == "request_extension") + } + test("client can set a custom operation id for ExecutePlan requests") { startDummyServer(0) client = SparkConnectClient @@ -927,4 +1036,59 @@ class DummySparkConnectService() extends SparkConnectServiceGrpc.SparkConnectSer responseObserver.onNext(response) responseObserver.onCompleted() } + + // Default operations stored in the mock session + private val defaultOperationStatuses = Map( + "default-op-1" -> + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_SUCCEEDED, + "default-op-2" -> + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_RUNNING) + + override def getStatus( + request: proto.GetStatusRequest, + responseObserver: StreamObserver[proto.GetStatusResponse]): Unit = { + val responseBuilder = proto.GetStatusResponse + .newBuilder() + .setSessionId(request.getSessionId) + .setServerSideSessionId(UUID.randomUUID().toString) + + if (request.hasOperationStatus) { + val opStatusRequest = request.getOperationStatus + val requestedIds = opStatusRequest.getOperationIdsList.asScala.toSeq + // Collect operation-status-level extensions from the request to echo back + val opStatusExtensions = opStatusRequest.getExtensionsList.asScala + + if (requestedIds.isEmpty) { + // No specific IDs requested - return all default operations + defaultOperationStatuses.foreach { case (opId, state) => + val statusBuilder = proto.GetStatusResponse.OperationStatus + .newBuilder() + .setOperationId(opId) + .setState(state) + opStatusExtensions.foreach(statusBuilder.addExtensions) + responseBuilder.addOperationStatuses(statusBuilder.build()) + } + } else { + // Return status for each requested operation ID + // Unknown operations return OPERATION_STATE_UNKNOWN + requestedIds.foreach { opId => + val state = defaultOperationStatuses.getOrElse( + opId, + proto.GetStatusResponse.OperationStatus.OperationState.OPERATION_STATE_UNKNOWN) + val statusBuilder = proto.GetStatusResponse.OperationStatus + .newBuilder() + .setOperationId(opId) + .setState(state) + opStatusExtensions.foreach(statusBuilder.addExtensions) + responseBuilder.addOperationStatuses(statusBuilder.build()) + } + } + } + + // Echo request-level extensions back in the response + request.getExtensionsList.asScala.foreach(responseBuilder.addExtensions) + + responseObserver.onNext(responseBuilder.build()) + responseObserver.onCompleted() + } } diff --git a/sql/connect/common/src/main/scala/org/apache/spark/sql/connect/client/CustomSparkConnectBlockingStub.scala b/sql/connect/common/src/main/scala/org/apache/spark/sql/connect/client/CustomSparkConnectBlockingStub.scala index 715da0df73491..ad39a3fb29f24 100644 --- a/sql/connect/common/src/main/scala/org/apache/spark/sql/connect/client/CustomSparkConnectBlockingStub.scala +++ b/sql/connect/common/src/main/scala/org/apache/spark/sql/connect/client/CustomSparkConnectBlockingStub.scala @@ -145,4 +145,17 @@ private[connect] class CustomSparkConnectBlockingStub( } } } + + def getStatus(request: GetStatusRequest): GetStatusResponse = { + grpcExceptionConverter.convert( + request.getSessionId, + request.getUserContext, + request.getClientType) { + retryHandler.retry { + stubState.responseValidator.verifyResponse { + stub.getStatus(request) + } + } + } + } } diff --git a/sql/connect/common/src/main/scala/org/apache/spark/sql/connect/client/SparkConnectClient.scala b/sql/connect/common/src/main/scala/org/apache/spark/sql/connect/client/SparkConnectClient.scala index 0fa7d9ada48ba..d9b9ba35b5e6c 100644 --- a/sql/connect/common/src/main/scala/org/apache/spark/sql/connect/client/SparkConnectClient.scala +++ b/sql/connect/common/src/main/scala/org/apache/spark/sql/connect/client/SparkConnectClient.scala @@ -33,7 +33,7 @@ import io.grpc._ import org.apache.spark.SparkBuildInfo.{spark_version => SPARK_VERSION} import org.apache.spark.SparkThrowable -import org.apache.spark.annotation.DeveloperApi +import org.apache.spark.annotation.{DeveloperApi, Experimental} import org.apache.spark.connect.proto import org.apache.spark.connect.proto.UserContext import org.apache.spark.internal.Logging @@ -496,6 +496,43 @@ private[sql] class SparkConnectClient( bstub.releaseSession(request.build()) } + /** + * Get status of operations in the session. + * + * @param operationIds + * Optional sequence of operation IDs to get status for. If empty, returns status of all + * operations in the session. + * @param operationExtensions + * Optional per-operation extensions to include in the OperationStatusRequest. + * @param requestExtensions + * Optional request-level extensions to include in the GetStatusRequest. + * @return + * The [[proto.GetStatusResponse]] for the requested operations, including any extensions. + */ + @Experimental + def getOperationStatuses( + operationIds: Seq[String] = Seq.empty, + operationExtensions: Seq[protobuf.Any] = Seq.empty, + requestExtensions: Seq[protobuf.Any] = Seq.empty): proto.GetStatusResponse = { + val requestBuilder = proto.GetStatusRequest + .newBuilder() + .setUserContext(userContext) + .setSessionId(sessionId) + .setClientType(userAgent) + + serverSideSessionId.foreach(session => + requestBuilder.setClientObservedServerSideSessionId(session)) + + val opStatusRequest = proto.GetStatusRequest.OperationStatusRequest.newBuilder() + operationIds.foreach(opStatusRequest.addOperationIds) + operationExtensions.foreach(opStatusRequest.addExtensions) + requestBuilder.setOperationStatus(opStatusRequest) + + requestExtensions.foreach(requestBuilder.addExtensions) + + bstub.getStatus(requestBuilder.build()) + } + private[this] val tags = new InheritableThreadLocal[mutable.Set[String]] { override def childValue(parent: mutable.Set[String]): mutable.Set[String] = { // Note: make a clone such that changes in the parent tags aren't reflected in diff --git a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/SparkConnectServerTest.scala b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/SparkConnectServerTest.scala index 77ede8e852e87..748e7623aba3a 100644 --- a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/SparkConnectServerTest.scala +++ b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/SparkConnectServerTest.scala @@ -196,12 +196,14 @@ trait SparkConnectServerTest extends SharedSparkSession { } } - protected def assertEventuallyNoActiveRpcs(): Unit = { + protected def eventuallyWithTimeout[T](f: => T): T = { Eventually.eventually(timeout(eventuallyTimeout)) { - assertNoActiveRpcs() + f } } + protected def assertEventuallyNoActiveRpcs(): Unit = eventuallyWithTimeout(assertNoActiveRpcs()) + protected def assertNoActiveExecutions(): Unit = { SparkConnectService.executionManager.listActiveExecutions match { case Left(_) => // cleaned up @@ -209,11 +211,8 @@ trait SparkConnectServerTest extends SharedSparkSession { } } - protected def assertEventuallyNoActiveExecutions(): Unit = { - Eventually.eventually(timeout(eventuallyTimeout)) { - assertNoActiveExecutions() - } - } + protected def assertEventuallyNoActiveExecutions(): Unit = + eventuallyWithTimeout(assertNoActiveExecutions()) protected def assertExecutionReleased(operationId: String): Unit = { SparkConnectService.executionManager.listActiveExecutions match { @@ -222,11 +221,8 @@ trait SparkConnectServerTest extends SharedSparkSession { } } - protected def assertEventuallyExecutionReleased(operationId: String): Unit = { - Eventually.eventually(timeout(eventuallyTimeout)) { - assertExecutionReleased(operationId) - } - } + protected def assertEventuallyExecutionReleased(operationId: String): Unit = + eventuallyWithTimeout(assertExecutionReleased(operationId)) // Get ExecutionHolder, assuming that only one execution is active protected def getExecutionHolder: ExecuteHolder = { @@ -235,11 +231,14 @@ trait SparkConnectServerTest extends SharedSparkSession { executions.head } - protected def eventuallyGetExecutionHolder: ExecuteHolder = { - Eventually.eventually(timeout(eventuallyTimeout)) { - getExecutionHolder - } - } + protected def getExecutionHolderForOperation(opId: String): ExecuteHolder = + SparkConnectService.executionManager.listExecuteHolders.find(_.key.operationId == opId).get + + protected def eventuallyGetExecutionHolderForOperation(opId: String): ExecuteHolder = + eventuallyWithTimeout(getExecutionHolderForOperation(opId)) + + protected def eventuallyGetExecutionHolder: ExecuteHolder = + eventuallyWithTimeout(getExecutionHolder) protected def withClient(sessionId: String = defaultSessionId, userId: String = defaultUserId)( f: SparkConnectClient => Unit): Unit = { diff --git a/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/GetStatusHandlerE2ESuite.scala b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/GetStatusHandlerE2ESuite.scala new file mode 100644 index 0000000000000..17d16162e31f9 --- /dev/null +++ b/sql/connect/server/src/test/scala/org/apache/spark/sql/connect/service/GetStatusHandlerE2ESuite.scala @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.spark.sql.connect.service + +import java.util.UUID + +import scala.jdk.CollectionConverters._ + +import org.scalatest.concurrent.Eventually + +import org.apache.spark.{SparkException, SparkRuntimeException} +import org.apache.spark.connect.proto +import org.apache.spark.connect.proto.GetStatusResponse.OperationStatus.OperationState +import org.apache.spark.sql.connect.SparkConnectServerTest + +class GetStatusHandlerE2ESuite extends SparkConnectServerTest { + + test("GetStatus tracks operation through lifecycle: RUNNING -> SUCCEEDED") { + withClient { client => + val plan = buildPlan("SELECT java_method('java.lang.Thread', 'sleep', 2000L) as value") + val iter = client.execute(plan) + val operationId = iter.next().getOperationId + + Eventually.eventually(timeout(eventuallyTimeout)) { + assert(SparkConnectService.executionManager.listExecuteHolders.length == 1) + } + + val runningStatuses = + client.getOperationStatuses(Seq(operationId)).getOperationStatusesList.asScala + assert(runningStatuses.size == 1) + assert(runningStatuses.head.getState == OperationState.OPERATION_STATE_RUNNING) + + while (iter.hasNext) iter.next() + assertEventuallyExecutionReleased(operationId) + + // Use eventually to skip the intermediate TERMINATING status + Eventually.eventually(timeout(eventuallyTimeout)) { + val succeededStatuses = + client.getOperationStatuses(Seq(operationId)).getOperationStatusesList.asScala + assert(succeededStatuses.size == 1) + assert(succeededStatuses.head.getState == OperationState.OPERATION_STATE_SUCCEEDED) + } + } + } + + test("GetStatus tracks operation through lifecycle: RUNNING -> CANCELLED") { + withClient { client => + val plan = buildPlan("SELECT java_method('java.lang.Thread', 'sleep', 3000L) as value") + val iter = client.execute(plan) + val operationId = iter.next().getOperationId + + Eventually.eventually(timeout(eventuallyTimeout)) { + assert(SparkConnectService.executionManager.listExecuteHolders.length == 1) + } + + val runningStatuses = + client.getOperationStatuses(Seq(operationId)).getOperationStatusesList.asScala + assert(runningStatuses.size == 1) + assert(runningStatuses.head.getState == OperationState.OPERATION_STATE_RUNNING) + + client.interruptOperation(operationId) + + intercept[SparkException] { + while (iter.hasNext) iter.next() + } + + assertEventuallyExecutionReleased(operationId) + + // Use eventually to skip the intermediate TERMINATING status + Eventually.eventually(timeout(eventuallyTimeout)) { + val cancelledStatuses = + client.getOperationStatuses(Seq(operationId)).getOperationStatusesList.asScala + assert(cancelledStatuses.size == 1) + assert(cancelledStatuses.head.getState == OperationState.OPERATION_STATE_CANCELLED) + } + } + } + + test("GetStatus returns FAILED for query with error") { + withClient { client => + // Use assert_true with a dynamic condition to trigger a runtime failure + val plan = buildPlan("SELECT assert_true(id < 0) FROM range(1)") + val iter = client.execute(plan) + val operationId = iter.next().getOperationId + + // Wait for the execution thread to finish before consuming the error from + // the iterator. This prevents a race where consuming the error triggers the + // client's ReleaseExecute, and removeExecuteHolder interrupts the execution + // thread while it's still in its finally block, which would override the + // termination reason from Failed to Canceled. + val holder = eventuallyGetExecutionHolderForOperation(operationId) + Eventually.eventually(timeout(eventuallyTimeout)) { + assert(!holder.isExecuteThreadRunnerAlive()) + } + + intercept[SparkRuntimeException] { + while (iter.hasNext) iter.next() + } + + assertEventuallyExecutionReleased(operationId) + + // Use eventually to skip the intermediate TERMINATING status + Eventually.eventually(timeout(eventuallyTimeout)) { + val statuses = + client.getOperationStatuses(Seq(operationId)).getOperationStatusesList.asScala + assert(statuses.size == 1) + assert(statuses.head.getOperationId == operationId) + assert(statuses.head.getState == OperationState.OPERATION_STATE_FAILED) + } + } + } + + test("GetStatus returns UNKNOWN for non-existent operation") { + withClient { client => + // Execute a simple query first to establish the session on the server + val plan = buildPlan("SELECT 1") + val iter = client.execute(plan) + while (iter.hasNext) iter.next() + + // Query for a random operation ID that was never created + val nonExistentOperationId = UUID.randomUUID().toString + val statuses = + client.getOperationStatuses(Seq(nonExistentOperationId)).getOperationStatusesList.asScala + assert(statuses.size == 1) + assert(statuses.head.getOperationId == nonExistentOperationId) + assert(statuses.head.getState == OperationState.OPERATION_STATE_UNKNOWN) + } + } + + test("GetStatus returns all operation statuses when no IDs specified") { + withClient { client => + val plan1 = buildPlan("SELECT 1 as first_value") + val iter1 = client.execute(plan1) + val operationId1 = iter1.next().getOperationId + while (iter1.hasNext) iter1.next() + assertEventuallyExecutionReleased(operationId1) + + val plan2 = buildPlan("SELECT assert_true(id < 0) FROM range(1)") + val iter2 = client.execute(plan2) + val operationId2 = iter2.next().getOperationId + + // Wait for the execution thread to finish before consuming the error. + // Same race condition as in the FAILED test above. + val holder2 = eventuallyGetExecutionHolderForOperation(operationId2) + Eventually.eventually(timeout(eventuallyTimeout)) { + assert(!holder2.isExecuteThreadRunnerAlive()) + } + + intercept[SparkRuntimeException] { + while (iter2.hasNext) iter2.next() + } + + assertEventuallyExecutionReleased(operationId2) + + // Use eventually to skip the intermediate TERMINATING status + Eventually.eventually(timeout(eventuallyTimeout)) { + val statuses = client.getOperationStatuses().getOperationStatusesList.asScala + val operationIdToStatus = statuses.map(s => s.getOperationId -> s.getState).toMap + + assert(statuses.size == 2) + assert(operationIdToStatus(operationId1) == OperationState.OPERATION_STATE_SUCCEEDED) + assert(operationIdToStatus(operationId2) == OperationState.OPERATION_STATE_FAILED) + } + } + } + + test("GetStatus returns session info even when no operation status is requested") { + // This test needs raw stub to send a request without operation_status field + withRawBlockingStub { stub => + // Execute a simple query to establish the session on the server. + val plan = buildPlan("SELECT 1") + val executeRequest = buildExecutePlanRequest(plan) + val sessionId = executeRequest.getSessionId + val operationId = executeRequest.getOperationId + + val iter = stub.executePlan(executeRequest) + while (iter.hasNext) iter.next() + + val releaseRequest = proto.ReleaseExecuteRequest + .newBuilder() + .setUserContext(userContext) + .setSessionId(sessionId) + .setOperationId(operationId) + .setReleaseAll(proto.ReleaseExecuteRequest.ReleaseAll.newBuilder().build()) + .build() + stub.releaseExecute(releaseRequest) + assertEventuallyExecutionReleased(operationId) + + val statusRequest = proto.GetStatusRequest + .newBuilder() + .setUserContext(userContext) + .setSessionId(sessionId) + .build() + + val response = stub.getStatus(statusRequest) + + assert(response.getSessionId == sessionId) + assert(response.getServerSideSessionId.nonEmpty) + assert(response.getOperationStatusesList.isEmpty) + } + } +} From 1e76dd8395ef82d2de3302d0baa0d39a9b1406f9 Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Fri, 27 Feb 2026 08:11:59 -0800 Subject: [PATCH 084/130] [SPARK-55519][SQL][TESTS] Fix V2FunctionBenchmark ### What changes were proposed in this pull request? Fix V2FunctionBenchmark, caused by SPARK-53968 (https://github.com/apache/spark/pull/52681) ``` $ build/sbt "sql/Test/runMain org.apache.spark.sql.connector.functions.V2FunctionBenchmark" ... [info] running (fork) org.apache.spark.sql.connector.functions.V2FunctionBenchmark [error] WARNING: Using incubator modules: jdk.incubator.vector [info] 13:43:41.084 WARN org.apache.spark.util.Utils: Your hostname, H27212-MAC-01.local, resolves to a loopback address: 127.0.0.1; using 10.242.159.140 instead (on interface en0) [info] 13:43:41.087 WARN org.apache.spark.util.Utils: Set SPARK_LOCAL_IP if you need to bind to another address [info] 13:43:41.260 WARN org.apache.hadoop.util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable [info] Running benchmark: scalar function (long + long) -> long, result_nullable = true codegen = true [info] Running case: native_long_add [error] Exception in thread "main" java.lang.NullPointerException: Cannot invoke "org.apache.spark.sql.catalyst.expressions.NumericEvalContext.evalMode()" because the return value of "org.apache.spark.sql.catalyst.expressions.BinaryArithmetic.evalContext()" is null [error] at org.apache.spark.sql.catalyst.expressions.BinaryArithmetic.evalMode(arithmetic.scala:201) [error] at org.apache.spark.sql.catalyst.expressions.BinaryArithmetic.failOnError(arithmetic.scala:209) [error] at org.apache.spark.sql.catalyst.expressions.BinaryArithmetic.initQueryContext(arithmetic.scala:251) [error] at org.apache.spark.sql.catalyst.expressions.SupportQueryContext.$init$(Expression.scala:670) [error] at org.apache.spark.sql.catalyst.expressions.BinaryArithmetic.(arithmetic.scala:193) [error] at org.apache.spark.sql.connector.functions.V2FunctionBenchmark$NativeAdd.(V2FunctionBenchmark.scala:111) [error] at org.apache.spark.sql.connector.functions.V2FunctionBenchmark$.$anonfun$scalarFunctionBenchmark$3(V2FunctionBenchmark.scala:88) ... ``` ### Why are the changes needed? Fix the benchmark. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Verified locally, GHA benchmark reports for JDK 17 and 21 are updated. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54540 from pan3793/SPARK-55744. Lead-authored-by: Cheng Pan Co-authored-by: pan3793 Signed-off-by: Dongjoon Hyun --- .../V2FunctionBenchmark-jdk21-results.txt | 56 +++++++++---------- .../V2FunctionBenchmark-results.txt | 56 +++++++++---------- .../functions/V2FunctionBenchmark.scala | 6 +- 3 files changed, 60 insertions(+), 58 deletions(-) diff --git a/sql/core/benchmarks/V2FunctionBenchmark-jdk21-results.txt b/sql/core/benchmarks/V2FunctionBenchmark-jdk21-results.txt index 363936391a630..38945637091fa 100644 --- a/sql/core/benchmarks/V2FunctionBenchmark-jdk21-results.txt +++ b/sql/core/benchmarks/V2FunctionBenchmark-jdk21-results.txt @@ -1,44 +1,44 @@ -OpenJDK 64-Bit Server VM 21.0.8+9-LTS on Linux 6.11.0-1018-azure +OpenJDK 64-Bit Server VM 21.0.10+7-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor scalar function (long + long) -> long, result_nullable = true codegen = true: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------------------------------------------ -native_long_add 9308 9710 686 53.7 18.6 1.0X -java_long_add_default 22865 23994 1622 21.9 45.7 0.4X -java_long_add_magic 11505 11983 804 43.5 23.0 0.8X -java_long_add_static_magic 11395 11452 49 43.9 22.8 0.8X -scala_long_add_default 23153 23807 968 21.6 46.3 0.4X -scala_long_add_magic 11562 11585 38 43.2 23.1 0.8X +native_long_add 9357 9828 787 53.4 18.7 1.0X +java_long_add_default 23136 23301 258 21.6 46.3 0.4X +java_long_add_magic 11555 11895 550 43.3 23.1 0.8X +java_long_add_static_magic 11457 11505 52 43.6 22.9 0.8X +scala_long_add_default 23402 23436 48 21.4 46.8 0.4X +scala_long_add_magic 11533 11657 149 43.4 23.1 0.8X -OpenJDK 64-Bit Server VM 21.0.8+9-LTS on Linux 6.11.0-1018-azure +OpenJDK 64-Bit Server VM 21.0.10+7-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor scalar function (long + long) -> long, result_nullable = false codegen = true: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------------------------------------------- -native_long_add 10290 10340 49 48.6 20.6 1.0X -java_long_add_default 22328 22368 42 22.4 44.7 0.5X -java_long_add_magic 11485 11572 118 43.5 23.0 0.9X -java_long_add_static_magic 9962 9980 19 50.2 19.9 1.0X -scala_long_add_default 22314 22377 104 22.4 44.6 0.5X -scala_long_add_magic 11503 12078 705 43.5 23.0 0.9X +native_long_add 10313 10344 34 48.5 20.6 1.0X +java_long_add_default 22388 22880 536 22.3 44.8 0.5X +java_long_add_magic 11491 11582 156 43.5 23.0 0.9X +java_long_add_static_magic 9980 13846 6696 50.1 20.0 1.0X +scala_long_add_default 22311 22344 30 22.4 44.6 0.5X +scala_long_add_magic 11541 11627 77 43.3 23.1 0.9X -OpenJDK 64-Bit Server VM 21.0.8+9-LTS on Linux 6.11.0-1018-azure +OpenJDK 64-Bit Server VM 21.0.10+7-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor scalar function (long + long) -> long, result_nullable = true codegen = false: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------------------------------------------- -native_long_add 22531 22615 108 22.2 45.1 1.0X -java_long_add_default 26677 26707 32 18.7 53.4 0.8X -java_long_add_magic 32551 32589 55 15.4 65.1 0.7X -java_long_add_static_magic 30687 30774 95 16.3 61.4 0.7X -scala_long_add_default 26292 26366 86 19.0 52.6 0.9X -scala_long_add_magic 32777 32981 245 15.3 65.6 0.7X +native_long_add 22692 22767 99 22.0 45.4 1.0X +java_long_add_default 26553 26619 68 18.8 53.1 0.9X +java_long_add_magic 32637 32804 285 15.3 65.3 0.7X +java_long_add_static_magic 30751 30819 60 16.3 61.5 0.7X +scala_long_add_default 26453 26489 42 18.9 52.9 0.9X +scala_long_add_magic 32736 32891 263 15.3 65.5 0.7X -OpenJDK 64-Bit Server VM 21.0.8+9-LTS on Linux 6.11.0-1018-azure +OpenJDK 64-Bit Server VM 21.0.10+7-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor scalar function (long + long) -> long, result_nullable = false codegen = false: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative -------------------------------------------------------------------------------------------------------------------------------------------------------------- -native_long_add 22593 22807 331 22.1 45.2 1.0X -java_long_add_default 26325 26370 46 19.0 52.7 0.9X -java_long_add_magic 32796 32827 42 15.2 65.6 0.7X -java_long_add_static_magic 30699 30874 163 16.3 61.4 0.7X -scala_long_add_default 26341 26371 45 19.0 52.7 0.9X -scala_long_add_magic 32794 32982 258 15.2 65.6 0.7X +native_long_add 22670 22722 79 22.1 45.3 1.0X +java_long_add_default 26424 26464 46 18.9 52.8 0.9X +java_long_add_magic 32737 33464 1195 15.3 65.5 0.7X +java_long_add_static_magic 30840 31079 380 16.2 61.7 0.7X +scala_long_add_default 26384 26482 123 19.0 52.8 0.9X +scala_long_add_magic 32628 32932 455 15.3 65.3 0.7X diff --git a/sql/core/benchmarks/V2FunctionBenchmark-results.txt b/sql/core/benchmarks/V2FunctionBenchmark-results.txt index 142394b25ccfa..adf9935875643 100644 --- a/sql/core/benchmarks/V2FunctionBenchmark-results.txt +++ b/sql/core/benchmarks/V2FunctionBenchmark-results.txt @@ -1,44 +1,44 @@ -OpenJDK 64-Bit Server VM 17.0.16+8-LTS on Linux 6.11.0-1018-azure +OpenJDK 64-Bit Server VM 17.0.18+8-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor scalar function (long + long) -> long, result_nullable = true codegen = true: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------------------------------------------ -native_long_add 9211 9245 49 54.3 18.4 1.0X -java_long_add_default 21996 22193 184 22.7 44.0 0.4X -java_long_add_magic 10647 10743 91 47.0 21.3 0.9X -java_long_add_static_magic 10559 10596 37 47.4 21.1 0.9X -scala_long_add_default 23193 23214 20 21.6 46.4 0.4X -scala_long_add_magic 10666 10686 30 46.9 21.3 0.9X +native_long_add 9112 9184 81 54.9 18.2 1.0X +java_long_add_default 22468 22546 89 22.3 44.9 0.4X +java_long_add_magic 10635 10671 31 47.0 21.3 0.9X +java_long_add_static_magic 10507 10579 63 47.6 21.0 0.9X +scala_long_add_default 23158 23211 83 21.6 46.3 0.4X +scala_long_add_magic 10646 10654 9 47.0 21.3 0.9X -OpenJDK 64-Bit Server VM 17.0.16+8-LTS on Linux 6.11.0-1018-azure +OpenJDK 64-Bit Server VM 17.0.18+8-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor scalar function (long + long) -> long, result_nullable = false codegen = true: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------------------------------------------- -native_long_add 9988 10158 200 50.1 20.0 1.0X -java_long_add_default 22418 22479 70 22.3 44.8 0.4X -java_long_add_magic 10631 10657 23 47.0 21.3 0.9X -java_long_add_static_magic 9864 9928 67 50.7 19.7 1.0X -scala_long_add_default 22269 22354 76 22.5 44.5 0.4X -scala_long_add_magic 10614 10670 52 47.1 21.2 0.9X +native_long_add 9953 9984 28 50.2 19.9 1.0X +java_long_add_default 22049 22151 105 22.7 44.1 0.5X +java_long_add_magic 10611 10636 27 47.1 21.2 0.9X +java_long_add_static_magic 9880 10707 1205 50.6 19.8 1.0X +scala_long_add_default 22129 22175 78 22.6 44.3 0.4X +scala_long_add_magic 10622 10712 95 47.1 21.2 0.9X -OpenJDK 64-Bit Server VM 17.0.16+8-LTS on Linux 6.11.0-1018-azure +OpenJDK 64-Bit Server VM 17.0.18+8-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor scalar function (long + long) -> long, result_nullable = true codegen = false: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative ------------------------------------------------------------------------------------------------------------------------------------------------------------- -native_long_add 22860 23095 317 21.9 45.7 1.0X -java_long_add_default 28130 28318 282 17.8 56.3 0.8X -java_long_add_magic 30689 32298 2467 16.3 61.4 0.7X -java_long_add_static_magic 30929 30969 35 16.2 61.9 0.7X -scala_long_add_default 26355 27156 1356 19.0 52.7 0.9X -scala_long_add_magic 30825 30861 33 16.2 61.7 0.7X +native_long_add 23353 23427 116 21.4 46.7 1.0X +java_long_add_default 28263 28280 15 17.7 56.5 0.8X +java_long_add_magic 31114 31224 166 16.1 62.2 0.8X +java_long_add_static_magic 31335 31963 1035 16.0 62.7 0.7X +scala_long_add_default 26408 27086 882 18.9 52.8 0.9X +scala_long_add_magic 31166 31292 136 16.0 62.3 0.7X -OpenJDK 64-Bit Server VM 17.0.16+8-LTS on Linux 6.11.0-1018-azure +OpenJDK 64-Bit Server VM 17.0.18+8-LTS on Linux 6.14.0-1017-azure AMD EPYC 7763 64-Core Processor scalar function (long + long) -> long, result_nullable = false codegen = false: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative -------------------------------------------------------------------------------------------------------------------------------------------------------------- -native_long_add 21895 21957 74 22.8 43.8 1.0X -java_long_add_default 25861 26173 537 19.3 51.7 0.8X -java_long_add_magic 30646 30681 31 16.3 61.3 0.7X -java_long_add_static_magic 30226 30256 32 16.5 60.5 0.7X -scala_long_add_default 26041 26108 70 19.2 52.1 0.8X -scala_long_add_magic 30668 30765 130 16.3 61.3 0.7X +native_long_add 22149 22214 110 22.6 44.3 1.0X +java_long_add_default 26026 26087 74 19.2 52.1 0.9X +java_long_add_magic 30800 30875 67 16.2 61.6 0.7X +java_long_add_static_magic 30936 31876 872 16.2 61.9 0.7X +scala_long_add_default 26061 26084 35 19.2 52.1 0.8X +scala_long_add_magic 30832 31138 451 16.2 61.7 0.7X diff --git a/sql/core/src/test/scala/org/apache/spark/sql/connector/functions/V2FunctionBenchmark.scala b/sql/core/src/test/scala/org/apache/spark/sql/connector/functions/V2FunctionBenchmark.scala index 5928699689175..5d2cc1694eb78 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/connector/functions/V2FunctionBenchmark.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/connector/functions/V2FunctionBenchmark.scala @@ -108,8 +108,10 @@ object V2FunctionBenchmark extends SqlBasedBenchmark { case class NativeAdd( left: Expression, right: Expression, - override val nullable: Boolean) extends BinaryArithmetic { - override val evalContext: NumericEvalContext = NumericEvalContext(EvalMode.LEGACY) + override val nullable: Boolean, + override val evalContext: NumericEvalContext = NumericEvalContext(EvalMode.LEGACY)) + extends BinaryArithmetic { + override def inputType: AbstractDataType = NumericType override def symbol: String = "+" From 6a0a905fcfbae242b67a6a14bea4535da53bf89b Mon Sep 17 00:00:00 2001 From: yangjie01 Date: Fri, 27 Feb 2026 08:35:54 -0800 Subject: [PATCH 085/130] [SPARK-55739][SQL] Optimize `OnHeapColumnVector.putIntsLittleEndian/putLongsLittleEndian` using `Platform.copyMemory` on little-endian platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? This pr refactored `putIntsLittleEndian` and `putLongsLittleEndian` in `OnHeapColumnVector` to hoist the `bigEndianPlatform` check outside the loop and use `Platform.copyMemory` for the common little-endian path. ### Why are the changes needed? For little-endian data input, `Platform.copyMemory` can be directly used, which is a memory copying method optimized by Spark. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? - Pass Github Actions - Rename the original code to `OldOnHeapColumnVector`, and compare the latency of the old and new `putIntsLittleEndian` and `putLongsLittleEndian` methods using JMH:

Benchmark Code (click to expand) ```java package org.apache.spark.sql.execution.vectorized; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import org.apache.spark.sql.types.DataTypes; BenchmarkMode(Mode.AverageTime) OutputTimeUnit(TimeUnit.MICROSECONDS) State(Scope.Thread) Fork(value = 1, jvmArgs = {"-Xms4G", "-Xmx4G"}) Warmup(iterations = 10, time = 1) Measurement(iterations = 10, time = 1) public class OnHeapColumnVectorJMHBenchmark { Param({"512", "1024", "4096", "8192", "16384"}) public int count; Param({"65536"}) public int i; private OnHeapColumnVector onHeapVectorInt; private OnHeapColumnVector onHeapVectorLong; private OldOnHeapColumnVector oldOnHeapVectorInt; private OldOnHeapColumnVector oldOnHeapVectorLong; private byte[] inputBytesInt; private byte[] inputBytesLong; Setup public void setup() { onHeapVectorInt = new OnHeapColumnVector(count, DataTypes.IntegerType); onHeapVectorLong = new OnHeapColumnVector(count, DataTypes.LongType); oldOnHeapVectorInt = new OldOnHeapColumnVector(count, DataTypes.IntegerType); oldOnHeapVectorLong = new OldOnHeapColumnVector(count, DataTypes.LongType); inputBytesInt = new byte[count * 4]; new java.util.Random().nextBytes(inputBytesInt); inputBytesLong = new byte[count * 8]; new java.util.Random().nextBytes(inputBytesLong); } TearDown public void tearDown() { onHeapVectorInt.close(); onHeapVectorLong.close(); oldOnHeapVectorInt.close(); oldOnHeapVectorLong.close(); } Benchmark public void onHeapPutIntsLittleEndian() { for (int n = 0; n < i; n++) { onHeapVectorInt.putIntsLittleEndian(0, count, inputBytesInt, 0); } } Benchmark public void OnHeapPutIntsLittleEndian_old() { for (int n = 0; n < i; n++) { oldOnHeapVectorInt.putIntsLittleEndian(0, count, inputBytesInt, 0); } } Benchmark public void onHeapPutLongsLittleEndian() { for (int n = 0; n < i; n++) { onHeapVectorLong.putLongsLittleEndian(0, count, inputBytesLong, 0); } } Benchmark public void OnHeapPutLongsLittleEndian_old() { for (int n = 0; n < i; n++) { oldOnHeapVectorLong.putLongsLittleEndian(0, count, inputBytesLong, 0); } } public static void main(String[] args) throws RunnerException { String filter = args.length > 0 ? args[0] : OnHeapColumnVectorJMHBenchmark.class.getSimpleName(); Options opt = new OptionsBuilder() .include(filter) .build(); new Runner(opt).run(); } } ```
**Benchmark results:** - Java 17.0.18+8-LTS ``` Benchmark (count) (loop) Mode Cnt Score Error Units OnHeapColumnVectorJMHBenchmark.OnHeapPutIntsLittleEndian_old 512 65536 avgt 10 11743.097 ± 53.078 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutIntsLittleEndian 512 65536 avgt 10 1703.095 ± 6.250 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutIntsLittleEndian_old 1024 65536 avgt 10 23448.338 ± 303.412 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutIntsLittleEndian 1024 65536 avgt 10 3008.894 ± 6.781 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutIntsLittleEndian_old 4096 65536 avgt 10 91491.559 ± 346.421 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutIntsLittleEndian 4096 65536 avgt 10 11303.794 ± 22.716 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutIntsLittleEndian_old 8192 65536 avgt 10 189572.012 ± 1575.984 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutIntsLittleEndian 8192 65536 avgt 10 42395.515 ± 353.775 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutIntsLittleEndian_old 16384 65536 avgt 10 379232.070 ± 4484.971 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutIntsLittleEndian 16384 65536 avgt 10 85881.927 ± 271.668 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutLongsLittleEndian_old 512 65536 avgt 10 12195.436 ± 104.812 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutLongsLittleEndian 512 65536 avgt 10 3849.975 ± 5.037 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutLongsLittleEndian_old 1024 65536 avgt 10 24296.856 ± 194.031 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutLongsLittleEndian 1024 65536 avgt 10 7436.610 ± 212.457 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutLongsLittleEndian_old 4096 65536 avgt 10 95374.778 ± 1560.388 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutLongsLittleEndian 4096 65536 avgt 10 44003.750 ± 599.336 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutLongsLittleEndian_old 8192 65536 avgt 10 189202.921 ± 322.925 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutLongsLittleEndian 8192 65536 avgt 10 88005.115 ± 60.030 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutLongsLittleEndian_old 16384 65536 avgt 10 379306.120 ± 4696.742 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutLongsLittleEndian 16384 65536 avgt 10 186179.355 ± 348.975 us/op ``` - Java 21.0.10+7-LTS ``` Benchmark (count) (loop) Mode Cnt Score Error Units OnHeapColumnVectorJMHBenchmark.OnHeapPutIntsLittleEndian_old 512 65536 avgt 10 1790.974 ± 11.692 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutIntsLittleEndian 512 65536 avgt 10 1848.389 ± 5.441 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutIntsLittleEndian_old 1024 65536 avgt 10 3023.715 ± 17.073 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutIntsLittleEndian 1024 65536 avgt 10 3113.747 ± 4.668 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutIntsLittleEndian_old 4096 65536 avgt 10 11076.221 ± 60.823 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutIntsLittleEndian 4096 65536 avgt 10 11180.941 ± 31.083 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutIntsLittleEndian_old 8192 65536 avgt 10 43625.483 ± 67.768 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutIntsLittleEndian 8192 65536 avgt 10 43086.341 ± 65.125 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutIntsLittleEndian_old 16384 65536 avgt 10 89393.103 ± 547.105 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutIntsLittleEndian 16384 65536 avgt 10 90173.425 ± 112.846 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutLongsLittleEndian_old 512 65536 avgt 10 3028.893 ± 91.114 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutLongsLittleEndian 512 65536 avgt 10 3068.886 ± 16.652 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutLongsLittleEndian_old 1024 65536 avgt 10 5961.539 ± 13.220 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutLongsLittleEndian 1024 65536 avgt 10 5902.645 ± 14.256 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutLongsLittleEndian_old 4096 65536 avgt 10 42444.759 ± 64.922 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutLongsLittleEndian 4096 65536 avgt 10 42379.760 ± 63.047 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutLongsLittleEndian_old 8192 65536 avgt 10 85712.614 ± 301.436 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutLongsLittleEndian 8192 65536 avgt 10 85106.127 ± 45.659 us/op OnHeapColumnVectorJMHBenchmark.OnHeapPutLongsLittleEndian_old 16384 65536 avgt 10 170694.785 ± 1030.468 us/op OnHeapColumnVectorJMHBenchmark.onHeapPutLongsLittleEndian 16384 65536 avgt 10 170435.863 ± 230.682 us/op ``` Based on the test results, the new code exhibits better optimization performance for Java 17. In a typical 4096 scenario, it achieves an **8-fold** performance improvement for the Int type and a **2-fold** performance improvement for the long type. For Java 21, due to its more aggressive Auto-vectorization optimization strategy, the new code does not demonstrate a distinct advantage, yet it also does not show a noticeable decline in performance.We can wait until Java 21 becomes the default version before considering how to make it even better. ### Was this patch authored or co-authored using generative AI tooling? No Closes #54532 from LuciferYang/SPARK-55739. Authored-by: yangjie01 Signed-off-by: Dongjoon Hyun --- .../vectorized/OnHeapColumnVector.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OnHeapColumnVector.java b/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OnHeapColumnVector.java index 0854c42db672a..a6472955d6732 100644 --- a/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OnHeapColumnVector.java +++ b/sql/core/src/main/java/org/apache/spark/sql/execution/vectorized/OnHeapColumnVector.java @@ -332,12 +332,14 @@ public void putInts(int rowId, int count, byte[] src, int srcIndex) { @Override public void putIntsLittleEndian(int rowId, int count, byte[] src, int srcIndex) { - int srcOffset = srcIndex + Platform.BYTE_ARRAY_OFFSET; - for (int i = 0; i < count; ++i, srcOffset += 4) { - intData[i + rowId] = Platform.getInt(src, srcOffset); - if (bigEndianPlatform) { - intData[i + rowId] = java.lang.Integer.reverseBytes(intData[i + rowId]); + if (bigEndianPlatform) { + int srcOffset = srcIndex + Platform.BYTE_ARRAY_OFFSET; + for (int i = 0; i < count; ++i, srcOffset += 4) { + intData[i + rowId] = java.lang.Integer.reverseBytes(Platform.getInt(src, srcOffset)); } + } else { + Platform.copyMemory(src, Platform.BYTE_ARRAY_OFFSET + srcIndex, intData, + Platform.INT_ARRAY_OFFSET + rowId * 4L, count * 4L); } } @@ -406,12 +408,14 @@ public void putLongs(int rowId, int count, byte[] src, int srcIndex) { @Override public void putLongsLittleEndian(int rowId, int count, byte[] src, int srcIndex) { - int srcOffset = srcIndex + Platform.BYTE_ARRAY_OFFSET; - for (int i = 0; i < count; ++i, srcOffset += 8) { - longData[i + rowId] = Platform.getLong(src, srcOffset); - if (bigEndianPlatform) { - longData[i + rowId] = java.lang.Long.reverseBytes(longData[i + rowId]); + if (bigEndianPlatform) { + int srcOffset = srcIndex + Platform.BYTE_ARRAY_OFFSET; + for (int i = 0; i < count; ++i, srcOffset += 8) { + longData[i + rowId] = java.lang.Long.reverseBytes(Platform.getLong(src, srcOffset)); } + } else { + Platform.copyMemory(src, Platform.BYTE_ARRAY_OFFSET + srcIndex, longData, + Platform.LONG_ARRAY_OFFSET + rowId * 8L, count * 8L); } } From 3f2575dcf3395634900c4df8ce97c98cefe316fd Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Fri, 27 Feb 2026 08:50:23 -0800 Subject: [PATCH 086/130] [SPARK-55745][TESTS] Add GHA benchmark reports for JDK 25 ### What changes were proposed in this pull request? Add GHA benchmark reports for JDK 25. ### Why are the changes needed? To help us identify performance change on JDK 25. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Review, as it's not a code change. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54542 from pan3793/jdk25-benchmark. Lead-authored-by: Cheng Pan Co-authored-by: pan3793 Signed-off-by: Dongjoon Hyun --- .../AvroReadBenchmark-jdk25-results.txt | 141 +++ .../AvroWriteBenchmark-jdk25-results.txt | 56 ++ .../ChecksumBenchmark-jdk25-results.txt | 13 + .../CoalescedRDDBenchmark-jdk25-results.txt | 40 + .../KryoBenchmark-jdk25-results.txt | 28 + .../KryoIteratorBenchmark-jdk25-results.txt | 28 + .../KryoSerializerBenchmark-jdk25-results.txt | 12 + .../LZ4TPCDSDataBenchmark-jdk25-results.txt | 17 + .../benchmarks/LZFBenchmark-jdk25-results.txt | 19 + ...StatusesConvertBenchmark-jdk25-results.txt | 13 + ...tatusesSerDeserBenchmark-jdk25-results.txt | 66 ++ .../PercentileHeapBenchmark-jdk25-results.txt | 41 + ...rsistenceEngineBenchmark-jdk25-results.txt | 18 + ...PropertiesCloneBenchmark-jdk25-results.txt | 40 + .../RocksDBBenchmark-jdk25-results.txt | 102 +++ .../SorterBenchmark-jdk25-results.txt | 29 + .../XORShiftRandomBenchmark-jdk25-results.txt | 44 + .../ZStandardBenchmark-jdk25-results.txt | 82 ++ ...andardTPCDSDataBenchmark-jdk25-results.txt | 49 ++ .../BLASBenchmark-jdk25-results.txt | 312 +++++++ ...DTSerializationBenchmark-jdk25-results.txt | 12 + ...alendarIntervalBenchmark-jdk25-results.txt | 11 + .../EnumTypeSetBenchmark-jdk25-results.txt | 105 +++ .../EscapePathBenchmark-jdk25-results.txt | 24 + ...enericArrayDataBenchmark-jdk25-results.txt | 10 + .../HashBenchmark-jdk25-results.txt | 70 ++ .../HashByteArrayBenchmark-jdk25-results.txt | 77 ++ .../benchmarks/HexBenchmark-jdk25-results.txt | 14 + ...mparableWrapperBenchmark-jdk25-results.txt | 7 + ...parkBloomFilterBenchmark-jdk25-results.txt | 300 +++++++ ...nsafeProjectionBenchmark-jdk25-results.txt | 14 + .../AggregateBenchmark-jdk25-results.txt | 148 ++++ ...nsiIntervalSortBenchmark-jdk25-results.txt | 28 + .../Base64Benchmark-jdk25-results.txt | 56 ++ .../BloomFilterBenchmark-jdk25-results.txt | 196 +++++ ...DataSourceWriteBenchmark-jdk25-results.txt | 70 ++ .../ByteArrayBenchmark-jdk25-results.txt | 27 + .../benchmarks/CSVBenchmark-jdk25-results.txt | 77 ++ .../CharVarcharBenchmark-jdk25-results.txt | 122 +++ .../CollationBenchmark-jdk25-results.txt | 88 ++ ...llationNonASCIIBenchmark-jdk25-results.txt | 88 ++ .../ColumnarBatchBenchmark-jdk25-results.txt | 59 ++ ...mpressionSchemeBenchmark-jdk25-results.txt | 137 +++ ...antColumnVectorBenchmark-jdk25-results.txt | 280 ++++++ .../DataSourceReadBenchmark-jdk25-results.txt | 438 ++++++++++ .../DatasetBenchmark-jdk25-results.txt | 46 + .../DateTimeBenchmark-jdk25-results.txt | 461 ++++++++++ .../DateTimeRebaseBenchmark-jdk25-results.txt | 154 ++++ .../EncodeBenchmark-jdk25-results.txt | 8 + ...yUnsafeRowArrayBenchmark-jdk25-results.txt | 45 + .../ExtractBenchmark-jdk25-results.txt | 104 +++ .../FilterPushdownBenchmark-jdk25-results.txt | 734 ++++++++++++++++ .../GenerateExecBenchmark-jdk25-results.txt | 12 + ...RelationMetricsBenchmark-jdk25-results.txt | 11 + .../InExpressionBenchmark-jdk25-results.txt | 740 ++++++++++++++++ ...nMemoryColumnarBenchmark-jdk25-results.txt | 12 + ...namicPartitionsBenchmark-jdk25-results.txt | 8 + .../IntervalBenchmark-jdk25-results.txt | 40 + .../JoinBenchmark-jdk25-results.txt | 82 ++ .../JsonBenchmark-jdk25-results.txt | 130 +++ .../LargeRowBenchmark-jdk25-results.txt | 26 + .../MakeDateTimeBenchmark-jdk25-results.txt | 22 + .../MetadataStructBenchmark-jdk25-results.txt | 46 + ...ricsAggregationBenchmark-jdk25-results.txt | 12 + .../MiscBenchmark-jdk25-results.txt | 127 +++ ...edSchemaPruningBenchmark-jdk25-results.txt | 53 ++ ...edSchemaPruningBenchmark-jdk25-results.txt | 53 ++ ...edicatePushDownBenchmark-jdk25-results.txt | 21 + ...edSchemaPruningBenchmark-jdk25-results.txt | 53 ++ .../PrimitiveArrayBenchmark-jdk25-results.txt | 12 + .../RangeBenchmark-jdk25-results.txt | 15 + .../RecursiveCTEBenchmark-jdk25-results.txt | 95 ++ .../SetOperationsBenchmark-jdk25-results.txt | 13 + .../SortBenchmark-jdk25-results.txt | 16 + ...BasicOperationsBenchmark-jdk25-results.txt | 144 ++++ ...StringFunctionsBenchmark-jdk25-results.txt | 11 + ...ExprEliminationBenchmark-jdk25-results.txt | 25 + .../TPCDSQueryBenchmark-jdk25-results.txt | 810 ++++++++++++++++++ ...deredAndProjectBenchmark-jdk25-results.txt | 12 + .../TopKBenchmark-jdk25-results.txt | 22 + .../benchmarks/UDFBenchmark-jdk25-results.txt | 59 ++ ...UnsafeArrayDataBenchmark-jdk25-results.txt | 33 + .../UpdateFieldsBenchmark-jdk25-results.txt | 26 + .../V2FunctionBenchmark-jdk25-results.txt | 44 + .../WideSchemaBenchmark-jdk25-results.txt | 158 ++++ .../WideTableBenchmark-jdk25-results.txt | 17 + ...veTableBenchmark-jdk25-hive2.3-results.txt | 11 + ...shAggregateExecBenchmark-jdk25-results.txt | 45 + .../OrcReadBenchmark-jdk25-results.txt | 222 +++++ 89 files changed, 8398 insertions(+) create mode 100644 connector/avro/benchmarks/AvroReadBenchmark-jdk25-results.txt create mode 100644 connector/avro/benchmarks/AvroWriteBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/ChecksumBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/CoalescedRDDBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/KryoBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/KryoIteratorBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/KryoSerializerBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/LZ4TPCDSDataBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/LZFBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/MapStatusesConvertBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/MapStatusesSerDeserBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/PercentileHeapBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/PersistenceEngineBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/PropertiesCloneBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/RocksDBBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/SorterBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/XORShiftRandomBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/ZStandardBenchmark-jdk25-results.txt create mode 100644 core/benchmarks/ZStandardTPCDSDataBenchmark-jdk25-results.txt create mode 100644 mllib-local/benchmarks/BLASBenchmark-jdk25-results.txt create mode 100644 mllib/benchmarks/UDTSerializationBenchmark-jdk25-results.txt create mode 100644 sql/catalyst/benchmarks/CalendarIntervalBenchmark-jdk25-results.txt create mode 100644 sql/catalyst/benchmarks/EnumTypeSetBenchmark-jdk25-results.txt create mode 100644 sql/catalyst/benchmarks/EscapePathBenchmark-jdk25-results.txt create mode 100644 sql/catalyst/benchmarks/GenericArrayDataBenchmark-jdk25-results.txt create mode 100644 sql/catalyst/benchmarks/HashBenchmark-jdk25-results.txt create mode 100644 sql/catalyst/benchmarks/HashByteArrayBenchmark-jdk25-results.txt create mode 100644 sql/catalyst/benchmarks/HexBenchmark-jdk25-results.txt create mode 100644 sql/catalyst/benchmarks/InternalRowComparableWrapperBenchmark-jdk25-results.txt create mode 100644 sql/catalyst/benchmarks/SparkBloomFilterBenchmark-jdk25-results.txt create mode 100644 sql/catalyst/benchmarks/UnsafeProjectionBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/AggregateBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/AnsiIntervalSortBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/Base64Benchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/BloomFilterBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/BuiltInDataSourceWriteBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/ByteArrayBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/CSVBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/CharVarcharBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/CollationBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/CollationNonASCIIBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/ColumnarBatchBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/CompressionSchemeBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/ConstantColumnVectorBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/DataSourceReadBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/DatasetBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/DateTimeBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/DateTimeRebaseBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/EncodeBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/ExternalAppendOnlyUnsafeRowArrayBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/ExtractBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/FilterPushdownBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/GenerateExecBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/HashedRelationMetricsBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/InExpressionBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/InMemoryColumnarBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/InsertTableWithDynamicPartitionsBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/IntervalBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/JoinBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/JsonBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/LargeRowBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/MakeDateTimeBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/MetadataStructBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/MetricsAggregationBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/MiscBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/OrcNestedSchemaPruningBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/OrcV2NestedSchemaPruningBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/ParquetNestedPredicatePushDownBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/ParquetNestedSchemaPruningBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/PrimitiveArrayBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/RangeBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/RecursiveCTEBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/SetOperationsBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/SortBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/StateStoreBasicOperationsBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/StringFunctionsBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/SubExprEliminationBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/TPCDSQueryBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/TakeOrderedAndProjectBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/TopKBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/UDFBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/UnsafeArrayDataBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/UpdateFieldsBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/V2FunctionBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/WideSchemaBenchmark-jdk25-results.txt create mode 100644 sql/core/benchmarks/WideTableBenchmark-jdk25-results.txt create mode 100644 sql/hive/benchmarks/InsertIntoHiveTableBenchmark-jdk25-hive2.3-results.txt create mode 100644 sql/hive/benchmarks/ObjectHashAggregateExecBenchmark-jdk25-results.txt create mode 100644 sql/hive/benchmarks/OrcReadBenchmark-jdk25-results.txt diff --git a/connector/avro/benchmarks/AvroReadBenchmark-jdk25-results.txt b/connector/avro/benchmarks/AvroReadBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..61c633debeead --- /dev/null +++ b/connector/avro/benchmarks/AvroReadBenchmark-jdk25-results.txt @@ -0,0 +1,141 @@ +================================================================================================ +SQL Single Numeric Column Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single TINYINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum 1548 1552 5 10.2 98.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single SMALLINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum 1542 1550 11 10.2 98.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single INT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum 1531 1533 3 10.3 97.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single BIGINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum 1444 1464 29 10.9 91.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single FLOAT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum 1459 1469 13 10.8 92.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single DOUBLE Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum 1444 1452 11 10.9 91.8 1.0X + + +================================================================================================ +Int and String Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Int and String Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum of columns 2641 2647 9 4.0 251.9 1.0X + + +================================================================================================ +Partitioned Table Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Partitioned Table: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Data column 1641 1644 4 9.6 104.3 1.0X +Partition column 1439 1448 12 10.9 91.5 1.1X +Both columns 1689 1699 14 9.3 107.4 1.0X + + +================================================================================================ +Repeated String Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Repeated String: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum of string length 1423 1433 14 7.4 135.7 1.0X + + +================================================================================================ +String with Nulls Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +String with Nulls Scan (0.0%): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum of string length 2369 2386 23 4.4 225.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +String with Nulls Scan (50.0%): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum of string length 1524 1532 12 6.9 145.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +String with Nulls Scan (95.0%): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum of string length 717 723 9 14.6 68.4 1.0X + + +================================================================================================ +Select All From Wide Columns +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Wide Column Scan from 1000 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Select of all columns 13711 13739 40 0.0 27421.9 1.0X + + +================================================================================================ +Single Column Scan From Wide Columns +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Single Column Scan from 100 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum of single column 1955 1957 3 0.5 1864.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Single Column Scan from 200 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum of single column 3734 3741 10 0.3 3561.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Single Column Scan from 300 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Sum of single column 5582 5607 35 0.2 5323.8 1.0X + + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Filters pushdown: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +w/o filters 4256 4264 10 0.2 4256.3 1.0X +pushdown disabled 4217 4226 13 0.2 4216.6 1.0X +w/ filters 1502 1513 10 0.7 1501.9 2.8X + diff --git a/connector/avro/benchmarks/AvroWriteBenchmark-jdk25-results.txt b/connector/avro/benchmarks/AvroWriteBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..8c512a560a792 --- /dev/null +++ b/connector/avro/benchmarks/AvroWriteBenchmark-jdk25-results.txt @@ -0,0 +1,56 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Avro writer benchmark: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Output Single Int Column 1690 1716 37 9.3 107.4 1.0X +Output Single Double Column 1645 1655 14 9.6 104.6 1.0X +Output Int and String Column 3351 3358 11 4.7 213.0 0.5X +Output Partitions 3192 3265 104 4.9 202.9 0.5X +Output Buckets 4125 4146 31 3.8 262.2 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Avro compression with different codec: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +BZIP2: 115116 115306 268 0.0 1151159.6 1.0X +DEFLATE: 6850 6875 36 0.0 68497.5 16.8X +UNCOMPRESSED: 5351 5370 27 0.0 53509.9 21.5X +SNAPPY: 4990 4996 9 0.0 49901.4 23.1X +XZ: 43245 43326 115 0.0 432445.1 2.7X +ZSTANDARD: 5288 5300 17 0.0 52880.9 21.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Avro deflate with different levels: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +DEFLATE: deflate.level=1 5064 5091 38 0.0 50642.5 1.0X +DEFLATE: deflate.level=3 5062 5071 13 0.0 50620.5 1.0X +DEFLATE: deflate.level=5 6797 6797 0 0.0 67971.4 0.7X +DEFLATE: deflate.level=7 6827 6851 34 0.0 68271.6 0.7X +DEFLATE: deflate.level=9 7171 7187 23 0.0 71706.7 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Avro xz with different levels: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +XZ: xz.level=1 12245 12278 47 0.0 122450.3 1.0X +XZ: xz.level=3 22439 22454 21 0.0 224390.4 0.5X +XZ: xz.level=5 42051 42158 152 0.0 420508.2 0.3X +XZ: xz.level=7 60646 60696 71 0.0 606455.6 0.2X +XZ: xz.level=9 135419 137445 2866 0.0 1354190.6 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Avro zstandard with different levels: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------------------- +ZSTANDARD: zstandard.level=1 5165 5224 83 0.0 51647.8 1.0X +ZSTANDARD: zstandard.level=1, zstandard.bufferPool.enabled=true 5168 5208 57 0.0 51679.3 1.0X +ZSTANDARD: zstandard.level=3 5342 5364 30 0.0 53424.0 1.0X +ZSTANDARD: zstandard.level=3, zstandard.bufferPool.enabled=true 5117 5176 83 0.0 51167.8 1.0X +ZSTANDARD: zstandard.level=5 5506 5527 30 0.0 55063.7 0.9X +ZSTANDARD: zstandard.level=5, zstandard.bufferPool.enabled=true 5311 5382 100 0.0 53109.9 1.0X +ZSTANDARD: zstandard.level=7 5739 5775 51 0.0 57390.7 0.9X +ZSTANDARD: zstandard.level=7, zstandard.bufferPool.enabled=true 5757 5784 39 0.0 57567.3 0.9X +ZSTANDARD: zstandard.level=9 6432 6471 56 0.0 64315.0 0.8X +ZSTANDARD: zstandard.level=9, zstandard.bufferPool.enabled=true 6305 6330 36 0.0 63045.8 0.8X + diff --git a/core/benchmarks/ChecksumBenchmark-jdk25-results.txt b/core/benchmarks/ChecksumBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..b992e3bceb529 --- /dev/null +++ b/core/benchmarks/ChecksumBenchmark-jdk25-results.txt @@ -0,0 +1,13 @@ +================================================================================================ +Benchmark Checksum Algorithms +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Checksum Algorithms: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Adler32 11116 11131 16 0.0 10855207.7 1.0X +CRC32 2771 2786 17 0.0 2705566.9 4.0X +CRC32C 2080 2133 52 0.0 2031392.0 5.3X + + diff --git a/core/benchmarks/CoalescedRDDBenchmark-jdk25-results.txt b/core/benchmarks/CoalescedRDDBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..43993ce2c4ad4 --- /dev/null +++ b/core/benchmarks/CoalescedRDDBenchmark-jdk25-results.txt @@ -0,0 +1,40 @@ +================================================================================================ +Coalesced RDD , large scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Coalesced RDD: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------- +Coalesce Num Partitions: 100 Num Hosts: 1 255 270 18 0.4 2549.8 1.0X +Coalesce Num Partitions: 100 Num Hosts: 5 124 127 4 0.8 1235.7 2.1X +Coalesce Num Partitions: 100 Num Hosts: 10 107 115 7 0.9 1070.2 2.4X +Coalesce Num Partitions: 100 Num Hosts: 20 105 107 3 1.0 1046.5 2.4X +Coalesce Num Partitions: 100 Num Hosts: 40 98 100 3 1.0 979.9 2.6X +Coalesce Num Partitions: 100 Num Hosts: 80 92 94 3 1.1 918.9 2.8X +Coalesce Num Partitions: 500 Num Hosts: 1 855 859 5 0.1 8549.7 0.3X +Coalesce Num Partitions: 500 Num Hosts: 5 252 253 1 0.4 2517.2 1.0X +Coalesce Num Partitions: 500 Num Hosts: 10 167 170 4 0.6 1666.1 1.5X +Coalesce Num Partitions: 500 Num Hosts: 20 127 128 2 0.8 1265.6 2.0X +Coalesce Num Partitions: 500 Num Hosts: 40 107 109 2 0.9 1074.4 2.4X +Coalesce Num Partitions: 500 Num Hosts: 80 110 115 8 0.9 1095.0 2.3X +Coalesce Num Partitions: 1000 Num Hosts: 1 1626 1630 4 0.1 16261.9 0.2X +Coalesce Num Partitions: 1000 Num Hosts: 5 406 409 3 0.2 4059.7 0.6X +Coalesce Num Partitions: 1000 Num Hosts: 10 241 241 1 0.4 2407.9 1.1X +Coalesce Num Partitions: 1000 Num Hosts: 20 168 172 4 0.6 1677.9 1.5X +Coalesce Num Partitions: 1000 Num Hosts: 40 140 143 4 0.7 1401.3 1.8X +Coalesce Num Partitions: 1000 Num Hosts: 80 122 126 5 0.8 1223.0 2.1X +Coalesce Num Partitions: 5000 Num Hosts: 1 7424 7440 16 0.0 74236.1 0.0X +Coalesce Num Partitions: 5000 Num Hosts: 5 1744 1754 10 0.1 17442.4 0.1X +Coalesce Num Partitions: 5000 Num Hosts: 10 917 926 8 0.1 9167.4 0.3X +Coalesce Num Partitions: 5000 Num Hosts: 20 511 513 3 0.2 5112.3 0.5X +Coalesce Num Partitions: 5000 Num Hosts: 40 315 317 2 0.3 3148.6 0.8X +Coalesce Num Partitions: 5000 Num Hosts: 80 205 207 3 0.5 2051.6 1.2X +Coalesce Num Partitions: 10000 Num Hosts: 1 13950 14030 126 0.0 139502.6 0.0X +Coalesce Num Partitions: 10000 Num Hosts: 5 3436 3441 5 0.0 34361.7 0.1X +Coalesce Num Partitions: 10000 Num Hosts: 10 1759 1762 5 0.1 17589.7 0.1X +Coalesce Num Partitions: 10000 Num Hosts: 20 922 926 3 0.1 9223.5 0.3X +Coalesce Num Partitions: 10000 Num Hosts: 40 513 514 2 0.2 5126.3 0.5X +Coalesce Num Partitions: 10000 Num Hosts: 80 300 302 4 0.3 2997.5 0.9X + + diff --git a/core/benchmarks/KryoBenchmark-jdk25-results.txt b/core/benchmarks/KryoBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..79f3fb8ea1b30 --- /dev/null +++ b/core/benchmarks/KryoBenchmark-jdk25-results.txt @@ -0,0 +1,28 @@ +================================================================================================ +Benchmark Kryo Unsafe vs safe Serialization +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Benchmark Kryo Unsafe vs safe Serialization: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +basicTypes: Int with unsafe:true 203 205 2 4.9 203.5 1.0X +basicTypes: Long with unsafe:true 195 197 3 5.1 194.9 1.0X +basicTypes: Float with unsafe:true 193 208 23 5.2 192.9 1.1X +basicTypes: Double with unsafe:true 197 199 3 5.1 196.6 1.0X +Array: Int with unsafe:true 2 2 0 496.4 2.0 101.0X +Array: Long with unsafe:true 4 4 0 281.6 3.6 57.3X +Array: Float with unsafe:true 2 2 0 485.0 2.1 98.7X +Array: Double with unsafe:true 4 4 0 281.5 3.6 57.3X +Map of string->Double with unsafe:true 27 28 1 36.7 27.3 7.5X +basicTypes: Int with unsafe:false 215 216 1 4.7 214.8 0.9X +basicTypes: Long with unsafe:false 231 233 3 4.3 230.9 0.9X +basicTypes: Float with unsafe:false 213 220 13 4.7 213.1 1.0X +basicTypes: Double with unsafe:false 213 215 2 4.7 212.6 1.0X +Array: Int with unsafe:false 13 14 0 74.1 13.5 15.1X +Array: Long with unsafe:false 21 22 1 47.2 21.2 9.6X +Array: Float with unsafe:false 6 6 0 175.9 5.7 35.8X +Array: Double with unsafe:false 9 10 1 107.4 9.3 21.8X +Map of string->Double with unsafe:false 29 29 1 35.1 28.5 7.1X + + diff --git a/core/benchmarks/KryoIteratorBenchmark-jdk25-results.txt b/core/benchmarks/KryoIteratorBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..4639a1001e830 --- /dev/null +++ b/core/benchmarks/KryoIteratorBenchmark-jdk25-results.txt @@ -0,0 +1,28 @@ +================================================================================================ +Benchmark of kryo asIterator on deserialization stream +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Benchmark of kryo asIterator on deserialization stream: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------------- +Colletion of int with 1 elements, useIterator: true 6 6 0 1.7 571.6 1.0X +Colletion of int with 10 elements, useIterator: true 14 14 0 0.7 1356.0 0.4X +Colletion of int with 100 elements, useIterator: true 87 89 1 0.1 8736.8 0.1X +Colletion of string with 1 elements, useIterator: true 8 8 0 1.3 760.2 0.8X +Colletion of string with 10 elements, useIterator: true 21 22 0 0.5 2095.2 0.3X +Colletion of string with 100 elements, useIterator: true 161 163 1 0.1 16088.6 0.0X +Colletion of Array[int] with 1 elements, useIterator: true 7 7 1 1.5 673.1 0.8X +Colletion of Array[int] with 10 elements, useIterator: true 19 20 0 0.5 1892.1 0.3X +Colletion of Array[int] with 100 elements, useIterator: true 147 148 1 0.1 14725.5 0.0X +Colletion of int with 1 elements, useIterator: false 6 6 0 1.7 599.4 1.0X +Colletion of int with 10 elements, useIterator: false 14 14 0 0.7 1384.3 0.4X +Colletion of int with 100 elements, useIterator: false 89 90 1 0.1 8912.1 0.1X +Colletion of string with 1 elements, useIterator: false 7 8 0 1.4 705.3 0.8X +Colletion of string with 10 elements, useIterator: false 21 22 0 0.5 2090.9 0.3X +Colletion of string with 100 elements, useIterator: false 158 159 0 0.1 15798.9 0.0X +Colletion of Array[int] with 1 elements, useIterator: false 7 7 0 1.5 671.3 0.9X +Colletion of Array[int] with 10 elements, useIterator: false 19 19 0 0.5 1879.6 0.3X +Colletion of Array[int] with 100 elements, useIterator: false 140 142 1 0.1 13983.2 0.0X + + diff --git a/core/benchmarks/KryoSerializerBenchmark-jdk25-results.txt b/core/benchmarks/KryoSerializerBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..3c6a780aea4f0 --- /dev/null +++ b/core/benchmarks/KryoSerializerBenchmark-jdk25-results.txt @@ -0,0 +1,12 @@ +================================================================================================ +Benchmark KryoPool vs old"pool of 1" implementation +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Benchmark KryoPool vs old"pool of 1" implementation: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------- +KryoPool:true 3355 4841 1526 0.0 6709103.0 1.0X +KryoPool:false 5653 8114 1886 0.0 11306116.1 0.6X + + diff --git a/core/benchmarks/LZ4TPCDSDataBenchmark-jdk25-results.txt b/core/benchmarks/LZ4TPCDSDataBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..0a03fd3e12f19 --- /dev/null +++ b/core/benchmarks/LZ4TPCDSDataBenchmark-jdk25-results.txt @@ -0,0 +1,17 @@ +================================================================================================ +Benchmark LZ4CompressionCodec +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Compression: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Compression 4 times 2611 2620 12 0.0 652865216.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Decompression: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Decompression 4 times 905 916 14 0.0 226166738.0 1.0X + + diff --git a/core/benchmarks/LZFBenchmark-jdk25-results.txt b/core/benchmarks/LZFBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..470ad20225c87 --- /dev/null +++ b/core/benchmarks/LZFBenchmark-jdk25-results.txt @@ -0,0 +1,19 @@ +================================================================================================ +Benchmark LZFCompressionCodec +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Compress small objects: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------- +Compression 256000000 int values in parallel 599 607 11 427.4 2.3 1.0X +Compression 256000000 int values single-threaded 596 596 1 429.9 2.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Compress large objects: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------- +Compression 1024 array values in 1 threads 42 48 5 0.0 40952.1 1.0X +Compression 1024 array values single-threaded 32 33 0 0.0 31512.4 1.3X + + diff --git a/core/benchmarks/MapStatusesConvertBenchmark-jdk25-results.txt b/core/benchmarks/MapStatusesConvertBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..265b19adc4eec --- /dev/null +++ b/core/benchmarks/MapStatusesConvertBenchmark-jdk25-results.txt @@ -0,0 +1,13 @@ +================================================================================================ +MapStatuses Convert Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +MapStatuses Convert: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Num Maps: 50000 Fetch partitions:500 674 681 7 0.0 674320697.0 1.0X +Num Maps: 50000 Fetch partitions:1000 1674 1706 30 0.0 1674417557.0 0.4X +Num Maps: 50000 Fetch partitions:1500 2677 2708 27 0.0 2677053327.0 0.3X + + diff --git a/core/benchmarks/MapStatusesSerDeserBenchmark-jdk25-results.txt b/core/benchmarks/MapStatusesSerDeserBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..b884084de7753 --- /dev/null +++ b/core/benchmarks/MapStatusesSerDeserBenchmark-jdk25-results.txt @@ -0,0 +1,66 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +200000 MapOutputs, 10 blocks w/ broadcast: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Serialization 85 89 4 2.3 426.5 1.0X +Deserialization 120 126 5 1.7 599.3 0.7X + +Compressed Serialized MapStatus sizes: 425.0 B +Compressed Serialized Broadcast MapStatus sizes: 3.2 MiB + + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +200000 MapOutputs, 10 blocks w/o broadcast: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +Serialization 82 83 1 2.4 409.0 1.0X +Deserialization 119 121 4 1.7 597.0 0.7X + +Compressed Serialized MapStatus sizes: 3.2 MiB +Compressed Serialized Broadcast MapStatus sizes: 0.0 B + + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +200000 MapOutputs, 100 blocks w/ broadcast: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +Serialization 161 165 8 1.2 802.8 1.0X +Deserialization 135 140 11 1.5 674.9 1.2X + +Compressed Serialized MapStatus sizes: 444.0 B +Compressed Serialized Broadcast MapStatus sizes: 14.3 MiB + + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +200000 MapOutputs, 100 blocks w/o broadcast: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +Serialization 141 145 6 1.4 706.0 1.0X +Deserialization 135 138 6 1.5 673.1 1.0X + +Compressed Serialized MapStatus sizes: 14.3 MiB +Compressed Serialized Broadcast MapStatus sizes: 0.0 B + + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +200000 MapOutputs, 1000 blocks w/ broadcast: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +Serialization 691 711 27 0.3 3453.5 1.0X +Deserialization 289 304 17 0.7 1446.1 2.4X + +Compressed Serialized MapStatus sizes: 566.0 B +Compressed Serialized Broadcast MapStatus sizes: 123.4 MiB + + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +200000 MapOutputs, 1000 blocks w/o broadcast: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------- +Serialization 557 565 9 0.4 2783.4 1.0X +Deserialization 289 304 22 0.7 1444.7 1.9X + +Compressed Serialized MapStatus sizes: 123.4 MiB +Compressed Serialized Broadcast MapStatus sizes: 0.0 B + + diff --git a/core/benchmarks/PercentileHeapBenchmark-jdk25-results.txt b/core/benchmarks/PercentileHeapBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..70954f1b3ff5b --- /dev/null +++ b/core/benchmarks/PercentileHeapBenchmark-jdk25-results.txt @@ -0,0 +1,41 @@ +================================================================================================ +PercentileHeap Operations +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +PercentileHeap Operations - Input Size: 10000: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------- +Percentile: 0.5 1 1 0 10.5 95.4 1.0X +Percentile: 0.9 1 1 0 18.4 54.4 1.8X +Percentile: 0.95 0 0 0 24.0 41.7 2.3X +Percentile: 0.99 0 0 0 31.7 31.5 3.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +PercentileHeap Operations - Input Size: 50000: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------- +Percentile: 0.5 5 5 0 10.2 98.4 1.0X +Percentile: 0.9 3 3 0 17.6 56.9 1.7X +Percentile: 0.95 2 2 0 22.7 44.0 2.2X +Percentile: 0.99 2 2 0 30.7 32.6 3.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +PercentileHeap Operations - Input Size: 100000: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +Percentile: 0.5 11 13 2 8.9 112.8 1.0X +Percentile: 0.9 6 6 0 16.9 59.2 1.9X +Percentile: 0.95 5 5 0 21.7 46.0 2.5X +Percentile: 0.99 3 4 0 30.2 33.2 3.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +PercentileHeap Operations - Input Size: 200000: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +Percentile: 0.5 24 25 1 8.4 119.5 1.0X +Percentile: 0.9 13 13 0 15.1 66.3 1.8X +Percentile: 0.95 10 11 2 20.3 49.2 2.4X +Percentile: 0.99 7 7 0 27.0 37.1 3.2X + + diff --git a/core/benchmarks/PersistenceEngineBenchmark-jdk25-results.txt b/core/benchmarks/PersistenceEngineBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..bdd9448c94957 --- /dev/null +++ b/core/benchmarks/PersistenceEngineBenchmark-jdk25-results.txt @@ -0,0 +1,18 @@ +================================================================================================ +PersistenceEngineBenchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +1000 Workers: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------------------- +ZooKeeperPersistenceEngine with JavaSerializer 5477 5586 102 0.0 5477165.0 1.0X +FileSystemPersistenceEngine with JavaSerializer 3367 3416 48 0.0 3367294.4 1.6X +FileSystemPersistenceEngine with JavaSerializer (lz4) 802 825 29 0.0 801540.6 6.8X +FileSystemPersistenceEngine with JavaSerializer (lzf) 2908 2953 40 0.0 2908101.5 1.9X +FileSystemPersistenceEngine with JavaSerializer (snappy) 739 779 40 0.0 739426.3 7.4X +FileSystemPersistenceEngine with JavaSerializer (zstd) 930 939 10 0.0 929834.9 5.9X +RocksDBPersistenceEngine with JavaSerializer 259 259 0 0.0 258543.7 21.2X +BlackHolePersistenceEngine 0 0 0 5.6 178.4 30706.9X + + diff --git a/core/benchmarks/PropertiesCloneBenchmark-jdk25-results.txt b/core/benchmarks/PropertiesCloneBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..3d58bd0655026 --- /dev/null +++ b/core/benchmarks/PropertiesCloneBenchmark-jdk25-results.txt @@ -0,0 +1,40 @@ +================================================================================================ +Properties Cloning +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Empty Properties: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SerializationUtils.clone 0 0 0 0.3 3015.0 1.0X +Utils.cloneProperties 0 0 0 25.0 40.0 75.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +System Properties: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SerializationUtils.clone 0 0 0 0.0 121077.0 1.0X +Utils.cloneProperties 0 0 0 0.3 3667.0 33.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Small Properties: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SerializationUtils.clone 0 0 0 0.0 221956.0 1.0X +Utils.cloneProperties 0 0 0 0.2 5520.0 40.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Medium Properties: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SerializationUtils.clone 1 1 0 0.0 789229.0 1.0X +Utils.cloneProperties 0 0 0 0.0 29104.0 27.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Large Properties: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SerializationUtils.clone 1 2 0 0.0 1490994.0 1.0X +Utils.cloneProperties 0 0 0 0.0 58309.0 25.6X + + diff --git a/core/benchmarks/RocksDBBenchmark-jdk25-results.txt b/core/benchmarks/RocksDBBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..eead3834da889 --- /dev/null +++ b/core/benchmarks/RocksDBBenchmark-jdk25-results.txt @@ -0,0 +1,102 @@ +================================================================================================ +RocksDB Lifecycle Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +RocksDB Lifecycle Operations: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +DB Creation 5 6 1 0.0 5270717.0 1.0X +DB Close 0 0 0 0.0 159457.0 33.1X + + +================================================================================================ +Sequential Operations Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Sequential Writes: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Indexed 22 23 2 0.0 21725.5 1.0X +No Index 16 17 0 0.1 16089.5 1.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Sequential Updates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Indexed 22 23 0 0.0 21587.2 1.0X +No Index 16 17 0 0.1 15863.5 1.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Sequential Deletes: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Indexed 11 12 1 0.1 10917.1 1.0X +No Index 13 13 1 0.1 12240.9 0.9X + + +================================================================================================ +Random Operations Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Random Writes: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Indexed 23 23 0 0.0 22191.4 1.0X +No Index 17 18 0 0.1 16667.5 1.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Random Updates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Indexed 22 22 0 0.0 21271.9 1.0X +No Index 16 16 1 0.1 15469.5 1.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Random Deletes: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Indexed 11 12 1 0.1 10912.7 1.0X +No Index 13 13 0 0.1 12210.3 0.9X + + +================================================================================================ +Natural Index Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Natural Index - Create Iterator: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Ascending 0 0 0 1065.6 0.9 1.0X +Descending 0 0 0 1012.9 1.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Natural Index - Iteration: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Ascending 1 1 0 0.8 1251.4 1.0X +Descending 1 2 0 0.8 1251.4 1.0X + + +================================================================================================ +Ref Index Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Ref Index - Create Iterator: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Ascending 0 0 0 888.9 1.1 1.0X +Descending 0 0 0 851.9 1.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Ref Index - Iteration: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Ascending 3 3 0 0.4 2453.2 1.0X +Descending 3 3 0 0.4 2473.0 1.0X + + diff --git a/core/benchmarks/SorterBenchmark-jdk25-results.txt b/core/benchmarks/SorterBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..1c6479e669e04 --- /dev/null +++ b/core/benchmarks/SorterBenchmark-jdk25-results.txt @@ -0,0 +1,29 @@ +================================================================================================ +key-value pairs sort +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +key-value pairs sort 25000000: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Tuple-sort using Arrays.sort() 15672 15696 34 1.6 626.9 1.0X +Tuple-sort using Arrays.parallelSort() 7237 7258 30 3.5 289.5 2.2X +KV-sort using Sorter 18783 19218 615 1.3 751.3 0.8X + + +================================================================================================ +primitive int array sort +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +primitive int array sort 25000000: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------- +Java Arrays.sort() on non-primitive int array 15597 15768 242 1.6 623.9 1.0X +Java Arrays.parallelSort() on non-primitive int array 6573 6973 566 3.8 262.9 2.4X +Java Arrays.sort() on primitive int array 374 374 0 66.9 15.0 41.7X +Java Arrays.parallelSort() on primitive int array 143 143 1 175.3 5.7 109.4X +Sorter without key reuse on primitive int array 8789 8826 52 2.8 351.5 1.8X +Sorter with key reuse on primitive int array 11558 11566 12 2.2 462.3 1.3X + + diff --git a/core/benchmarks/XORShiftRandomBenchmark-jdk25-results.txt b/core/benchmarks/XORShiftRandomBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..842c0c8f76ac7 --- /dev/null +++ b/core/benchmarks/XORShiftRandomBenchmark-jdk25-results.txt @@ -0,0 +1,44 @@ +================================================================================================ +Pseudo random +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +nextInt: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java.util.Random 1189 1189 0 84.1 11.9 1.0X +XORShiftRandom 190 190 0 526.5 1.9 6.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +nextLong: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java.util.Random 2363 2363 1 42.3 23.6 1.0X +XORShiftRandom 399 401 2 250.9 4.0 5.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +nextDouble: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java.util.Random 2376 2378 2 42.1 23.8 1.0X +XORShiftRandom 375 375 0 267.0 3.7 6.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +nextGaussian: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java.util.Random 7032 7034 2 14.2 70.3 1.0X +XORShiftRandom 3082 3086 4 32.4 30.8 2.3X + + +================================================================================================ +hash seed +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Hash seed: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +XORShiftRandom.hashSeed 1 1 0 12475.3 0.1 1.0X + + diff --git a/core/benchmarks/ZStandardBenchmark-jdk25-results.txt b/core/benchmarks/ZStandardBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..f323144859d34 --- /dev/null +++ b/core/benchmarks/ZStandardBenchmark-jdk25-results.txt @@ -0,0 +1,82 @@ +================================================================================================ +Benchmark ZStandardCompressionCodec +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Benchmark ZStandardCompressionCodec: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +Compression 10000 times at level 1 without buffer pool 684 688 5 0.0 68373.3 1.0X +Compression 10000 times at level 2 without buffer pool 705 706 1 0.0 70477.2 1.0X +Compression 10000 times at level 3 without buffer pool 808 811 4 0.0 80840.4 0.8X +Compression 10000 times at level 1 with buffer pool 607 608 1 0.0 60689.7 1.1X +Compression 10000 times at level 2 with buffer pool 642 644 3 0.0 64249.8 1.1X +Compression 10000 times at level 3 with buffer pool 755 756 1 0.0 75526.9 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Benchmark ZStandardCompressionCodec: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------ +Decompression 10000 times from level 1 without buffer pool 641 642 1 0.0 64127.5 1.0X +Decompression 10000 times from level 2 without buffer pool 638 638 0 0.0 63773.7 1.0X +Decompression 10000 times from level 3 without buffer pool 639 642 4 0.0 63885.6 1.0X +Decompression 10000 times from level 1 with buffer pool 573 573 0 0.0 57305.5 1.1X +Decompression 10000 times from level 2 with buffer pool 572 572 1 0.0 57182.2 1.1X +Decompression 10000 times from level 3 with buffer pool 573 573 0 0.0 57254.9 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Parallel Compression at level 3: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parallel Compression with 0 workers 65 66 1 0.0 508811.1 1.0X +Parallel Compression with 1 workers 53 55 2 0.0 417964.2 1.2X +Parallel Compression with 2 workers 44 45 1 0.0 340066.6 1.5X +Parallel Compression with 4 workers 39 41 1 0.0 303600.2 1.7X +Parallel Compression with 8 workers 40 42 1 0.0 314390.5 1.6X +Parallel Compression with 16 workers 44 46 1 0.0 341098.9 1.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Parallel Compression at level 9: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parallel Compression with 0 workers 233 234 1 0.0 1817871.6 1.0X +Parallel Compression with 1 workers 256 257 2 0.0 1998441.4 0.9X +Parallel Compression with 2 workers 139 143 4 0.0 1083158.0 1.7X +Parallel Compression with 4 workers 125 129 2 0.0 977189.6 1.9X +Parallel Compression with 8 workers 129 131 2 0.0 1004162.1 1.8X +Parallel Compression with 16 workers 128 131 2 0.0 998834.2 1.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Compression at level 1: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Compression by strategy -1 53 54 1 0.0 412288.7 1.0X +Compression by strategy 1 53 54 1 0.0 412148.9 1.0X +Compression by strategy 3 87 88 1 0.0 677620.0 0.6X +Compression by strategy 5 232 234 4 0.0 1815805.6 0.2X +Compression by strategy 7 258 259 1 0.0 2017867.7 0.2X +Compression by strategy 9 259 260 1 0.0 2023238.5 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Compression at level 3: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Compression by strategy -1 65 66 2 0.0 507586.3 1.0X +Compression by strategy 1 49 50 1 0.0 382064.8 1.3X +Compression by strategy 3 85 86 1 0.0 666476.1 0.8X +Compression by strategy 5 231 232 1 0.0 1803639.7 0.3X +Compression by strategy 7 271 272 1 0.0 2119308.7 0.2X +Compression by strategy 9 271 272 1 0.0 2121016.4 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Compression at level 9: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Compression by strategy -1 233 234 1 0.0 1817542.6 1.0X +Compression by strategy 1 49 50 1 0.0 384895.0 4.7X +Compression by strategy 3 86 87 1 0.0 668682.2 2.7X +Compression by strategy 5 232 234 1 0.0 1816299.4 1.0X +Compression by strategy 7 273 274 2 0.0 2131039.6 0.9X +Compression by strategy 9 273 274 1 0.0 2133140.7 0.9X + + diff --git a/core/benchmarks/ZStandardTPCDSDataBenchmark-jdk25-results.txt b/core/benchmarks/ZStandardTPCDSDataBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..02c2a9182d4ce --- /dev/null +++ b/core/benchmarks/ZStandardTPCDSDataBenchmark-jdk25-results.txt @@ -0,0 +1,49 @@ +================================================================================================ +Benchmark ZStandardCompressionCodec +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Compression: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------------- +Compression 4 times at level 1 without buffer pool 2563 2564 2 0.0 640678929.3 1.0X +Compression 4 times at level 2 without buffer pool 4175 4176 1 0.0 1043694084.8 0.6X +Compression 4 times at level 3 without buffer pool 6278 6279 2 0.0 1569384290.5 0.4X +Compression 4 times at level 1 with buffer pool 2563 2564 1 0.0 640717901.0 1.0X +Compression 4 times at level 2 with buffer pool 4177 4178 2 0.0 1044180994.0 0.6X +Compression 4 times at level 3 with buffer pool 6277 6280 4 0.0 1569310272.0 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Decompression: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +Decompression 4 times from level 1 without buffer pool 848 869 20 0.0 211906407.2 1.0X +Decompression 4 times from level 2 without buffer pool 1095 1112 24 0.0 273679919.2 0.8X +Decompression 4 times from level 3 without buffer pool 1344 1361 24 0.0 336096769.5 0.6X +Decompression 4 times from level 1 with buffer pool 837 857 22 0.0 209332055.5 1.0X +Decompression 4 times from level 2 with buffer pool 1117 1129 17 0.0 279233593.8 0.8X +Decompression 4 times from level 3 with buffer pool 1351 1352 1 0.0 337755217.5 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Parallel Compression at level 3: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parallel Compression with 0 workers 2081 2086 7 0.0 520246872.0 1.0X +Parallel Compression with 1 workers 2106 2107 2 0.0 526479842.3 1.0X +Parallel Compression with 2 workers 1090 1092 3 0.0 272445371.0 1.9X +Parallel Compression with 4 workers 759 771 19 0.0 189775705.3 2.7X +Parallel Compression with 8 workers 776 784 8 0.0 193907564.8 2.7X +Parallel Compression with 16 workers 888 896 7 0.0 222053162.3 2.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Parallel Compression at level 9: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parallel Compression with 0 workers 8321 8325 6 0.0 2080279947.5 1.0X +Parallel Compression with 1 workers 6909 6911 3 0.0 1727358566.5 1.2X +Parallel Compression with 2 workers 3646 3653 10 0.0 911618765.8 2.3X +Parallel Compression with 4 workers 3108 3115 9 0.0 777076163.8 2.7X +Parallel Compression with 8 workers 3462 3469 9 0.0 865546341.3 2.4X +Parallel Compression with 16 workers 3705 3723 26 0.0 926138190.7 2.2X + + diff --git a/mllib-local/benchmarks/BLASBenchmark-jdk25-results.txt b/mllib-local/benchmarks/BLASBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..97ab764a2fc50 --- /dev/null +++ b/mllib-local/benchmarks/BLASBenchmark-jdk25-results.txt @@ -0,0 +1,312 @@ +================================================================================================ +daxpy +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +daxpy: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 154 166 8 647.3 1.5 1.0X +java 127 134 3 789.1 1.3 1.2X + + +================================================================================================ +saxpy +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +saxpy: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 73 77 4 1373.2 0.7 1.0X +java 61 65 3 1648.8 0.6 1.2X + + +================================================================================================ +dcopy +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dcopy: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 127 147 6 789.2 1.3 1.0X +java 124 129 2 806.6 1.2 1.0X + + +================================================================================================ +scopy +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +scopy: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 67 73 4 1486.1 0.7 1.0X +java 62 66 2 1612.6 0.6 1.1X + + +================================================================================================ +ddot +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +ddot: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 95 96 0 1047.6 1.0 1.0X +java 48 51 2 2075.1 0.5 2.0X + + +================================================================================================ +sdot +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sdot: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 94 94 0 1066.9 0.9 1.0X +java 23 25 1 4342.7 0.2 4.1X + + +================================================================================================ +dnrm2 +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dnrm2: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 143 144 2 697.6 1.4 1.0X +java 33 34 1 2995.0 0.3 4.3X + + +================================================================================================ +snrm2 +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +snrm2: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 108 109 2 922.9 1.1 1.0X +java 17 17 1 6007.1 0.2 6.5X + + +================================================================================================ +dscal +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dscal: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 107 121 8 934.5 1.1 1.0X +java 107 112 3 930.4 1.1 1.0X + + +================================================================================================ +sscal +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sscal: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 55 58 1 1812.8 0.6 1.0X +java 53 57 2 1873.8 0.5 1.0X + + +================================================================================================ +dgemv[N] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dgemv[N]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 97 97 1 1033.2 1.0 1.0X +java 25 26 1 4049.5 0.2 3.9X + + +================================================================================================ +dgemv[T] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dgemv[T]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 94 94 0 1063.6 0.9 1.0X +java 23 24 1 4303.7 0.2 4.0X + + +================================================================================================ +sgemv[N] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sgemv[N]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 95 96 1 1047.8 1.0 1.0X +java 12 13 1 8363.4 0.1 8.0X + + +================================================================================================ +sgemv[T] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sgemv[T]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 94 94 1 1069.4 0.9 1.0X +java 12 14 1 8046.6 0.1 7.5X + + +================================================================================================ +dger +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dger: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 128 147 6 779.6 1.3 1.0X +java 104 108 2 962.8 1.0 1.2X + + +================================================================================================ +dspmv[U] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dspmv[U]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 68 68 1 736.3 1.4 1.0X +java 13 14 0 3879.7 0.3 5.3X + + +================================================================================================ +dspr[U] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dspr[U]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 86 91 4 581.6 1.7 1.0X +java 87 89 1 576.8 1.7 1.0X + + +================================================================================================ +dsyr[U] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dsyr[U]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 127 146 6 393.2 2.5 1.0X +java 126 130 2 396.0 2.5 1.0X + + +================================================================================================ +dgemm[N,N] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dgemm[N,N]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 672 675 6 1487.3 0.7 1.0X +java 66 75 6 15198.4 0.1 10.2X + + +================================================================================================ +dgemm[N,T] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dgemm[N,T]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 673 676 3 1484.9 0.7 1.0X +java 66 75 6 15126.5 0.1 10.2X + + +================================================================================================ +dgemm[T,N] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dgemm[T,N]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 908 909 2 1101.5 0.9 1.0X +java 65 75 6 15289.8 0.1 13.9X + + +================================================================================================ +dgemm[T,T] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dgemm[T,T]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 954 956 4 1047.9 1.0 1.0X +java 66 75 6 15227.8 0.1 14.5X + + +================================================================================================ +sgemm[N,N] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sgemm[N,N]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 647 648 3 1545.7 0.6 1.0X +java 39 40 1 25559.1 0.0 16.5X + + +================================================================================================ +sgemm[N,T] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sgemm[N,T]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 654 655 2 1529.1 0.7 1.0X +java 40 40 1 25239.4 0.0 16.5X + + +================================================================================================ +sgemm[T,N] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sgemm[T,N]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 908 910 3 1100.7 0.9 1.0X +java 39 40 1 25385.0 0.0 23.1X + + +================================================================================================ +sgemm[T,T] +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sgemm[T,T]: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +f2j 948 950 3 1055.0 0.9 1.0X +java 39 41 1 25463.7 0.0 24.1X + + diff --git a/mllib/benchmarks/UDTSerializationBenchmark-jdk25-results.txt b/mllib/benchmarks/UDTSerializationBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..c1d79a714d570 --- /dev/null +++ b/mllib/benchmarks/UDTSerializationBenchmark-jdk25-results.txt @@ -0,0 +1,12 @@ +================================================================================================ +VectorUDT de/serialization +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +VectorUDT de/serialization: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +serialize 184 194 7 0.0 183662.7 1.0X +deserialize 106 112 6 0.0 105891.1 1.7X + + diff --git a/sql/catalyst/benchmarks/CalendarIntervalBenchmark-jdk25-results.txt b/sql/catalyst/benchmarks/CalendarIntervalBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..c4869b3f33af6 --- /dev/null +++ b/sql/catalyst/benchmarks/CalendarIntervalBenchmark-jdk25-results.txt @@ -0,0 +1,11 @@ +================================================================================================ +CalendarInterval +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +CalendarInterval: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Call setInterval & getInterval 1042 1043 1 128.8 7.8 1.0X + + diff --git a/sql/catalyst/benchmarks/EnumTypeSetBenchmark-jdk25-results.txt b/sql/catalyst/benchmarks/EnumTypeSetBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..5ccba9e78521e --- /dev/null +++ b/sql/catalyst/benchmarks/EnumTypeSetBenchmark-jdk25-results.txt @@ -0,0 +1,105 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test contains use empty Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 1 1 0 771.1 1.3 1.0X +Use EnumSet 2 2 0 574.3 1.7 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test contains use 1 item Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 2 2 0 510.2 2.0 1.0X +Use EnumSet 2 2 0 530.6 1.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test contains use 3 items Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 2 2 0 552.0 1.8 1.0X +Use EnumSet 2 2 0 546.6 1.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test contains use 5 items Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 10 10 0 110.0 9.1 1.0X +Use EnumSet 2 2 0 590.2 1.7 5.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test contains use 11 items Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 10 10 0 107.7 9.3 1.0X +Use EnumSet 2 2 0 547.0 1.8 5.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test create empty Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 0 0 0 395.0 2.5 1.0X +Use EnumSet 1 1 0 131.9 7.6 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test create 1 item Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 3 3 0 35.3 28.3 1.0X +Use EnumSet 0 0 0 291.4 3.4 8.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test create 3 items Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 10 10 0 10.3 97.1 1.0X +Use EnumSet 1 1 0 143.9 6.9 14.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test create 5 items Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 39 41 0 2.6 390.5 1.0X +Use EnumSet 1 1 0 141.9 7.0 55.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test create 11 items Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 63 64 0 1.6 628.7 1.0X +Use EnumSet 1 1 0 132.2 7.6 83.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test create and contains use empty Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 4 4 0 256.0 3.9 1.0X +Use EnumSet 7 7 0 160.8 6.2 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test create and contains use 1 item Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 13 14 0 84.1 11.9 1.0X +Use EnumSet 7 7 0 162.5 6.2 1.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test create and contains use 3 items Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 27 28 0 40.4 24.8 1.0X +Use EnumSet 6 7 0 169.5 5.9 4.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test create and contains use 5 items Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Use HashSet 62 63 0 17.7 56.5 1.0X +Use EnumSet 7 7 0 153.8 6.5 8.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test create and contains use 11 items Set: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Use HashSet 87 87 0 12.7 78.7 1.0X +Use EnumSet 7 8 0 156.0 6.4 12.3X + diff --git a/sql/catalyst/benchmarks/EscapePathBenchmark-jdk25-results.txt b/sql/catalyst/benchmarks/EscapePathBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..e017e9fd01c7e --- /dev/null +++ b/sql/catalyst/benchmarks/EscapePathBenchmark-jdk25-results.txt @@ -0,0 +1,24 @@ +================================================================================================ +Escape +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Escape Tests: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Legacy 4201 4214 6 0.2 4200.7 1.0X +New 905 910 4 1.1 904.6 4.6X + + +================================================================================================ +Unescape +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Unescape Tests: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Legacy 5510 5524 24 0.2 5509.7 1.0X +New 628 632 9 1.6 628.5 8.8X + + diff --git a/sql/catalyst/benchmarks/GenericArrayDataBenchmark-jdk25-results.txt b/sql/catalyst/benchmarks/GenericArrayDataBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..d3d12b0ebb80a --- /dev/null +++ b/sql/catalyst/benchmarks/GenericArrayDataBenchmark-jdk25-results.txt @@ -0,0 +1,10 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +constructor: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +arrayOfAny 3 3 0 3221.8 0.3 1.0X +arrayOfAnyAsObject 3 3 0 3221.6 0.3 1.0X +arrayOfAnyAsSeq 371 372 1 26.9 37.1 0.0X +arrayOfInt 378 384 10 26.4 37.8 0.0X +arrayOfIntAsObject 370 372 3 27.0 37.0 0.0X + diff --git a/sql/catalyst/benchmarks/HashBenchmark-jdk25-results.txt b/sql/catalyst/benchmarks/HashBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..078f7e5ba2015 --- /dev/null +++ b/sql/catalyst/benchmarks/HashBenchmark-jdk25-results.txt @@ -0,0 +1,70 @@ +================================================================================================ +single ints +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Hash For single ints: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +interpreted version 2103 2104 0 255.2 3.9 1.0X +codegen version 3186 3186 1 168.5 5.9 0.7X +codegen version 64-bit 3198 3206 12 167.9 6.0 0.7X +codegen HiveHash version 2550 2553 3 210.5 4.8 0.8X + + +================================================================================================ +single longs +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Hash For single longs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +interpreted version 2893 2901 11 185.6 5.4 1.0X +codegen version 4735 4741 8 113.4 8.8 0.6X +codegen version 64-bit 3788 3792 5 141.7 7.1 0.8X +codegen HiveHash version 3247 3250 3 165.3 6.0 0.9X + + +================================================================================================ +normal +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Hash For normal: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +interpreted version 1359 1362 5 1.5 647.8 1.0X +codegen version 1734 1734 0 1.2 826.7 0.8X +codegen version 64-bit 722 723 3 2.9 344.1 1.9X +codegen HiveHash version 3686 3688 2 0.6 1757.8 0.4X + + +================================================================================================ +array +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Hash For array: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +interpreted version 998 1000 2 0.1 7616.1 1.0X +codegen version 3592 3594 4 0.0 27402.0 0.3X +codegen version 64-bit 2445 2445 0 0.1 18650.8 0.4X +codegen HiveHash version 696 696 0 0.2 5308.3 1.4X + + +================================================================================================ +map +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Hash For map: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +interpreted version 0 0 0 85.3 11.7 1.0X +codegen version 232 232 0 0.0 56599.0 0.0X +codegen version 64-bit 155 155 0 0.0 37843.5 0.0X +codegen HiveHash version 25 25 0 0.2 6172.1 0.0X + + diff --git a/sql/catalyst/benchmarks/HashByteArrayBenchmark-jdk25-results.txt b/sql/catalyst/benchmarks/HashByteArrayBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..3f3ca20affb80 --- /dev/null +++ b/sql/catalyst/benchmarks/HashByteArrayBenchmark-jdk25-results.txt @@ -0,0 +1,77 @@ +================================================================================================ +Benchmark for MurMurHash 3 and xxHash64 +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Hash byte arrays with length 8: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Murmur3_x86_32 12 12 0 180.9 5.5 1.0X +xxHash 64-bit 11 11 0 193.1 5.2 1.1X +HiveHasher 16 16 0 129.8 7.7 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Hash byte arrays with length 16: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Murmur3_x86_32 17 17 0 126.0 7.9 1.0X +xxHash 64-bit 14 14 0 153.8 6.5 1.2X +HiveHasher 27 27 0 78.8 12.7 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Hash byte arrays with length 24: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Murmur3_x86_32 23 23 0 91.5 10.9 1.0X +xxHash 64-bit 17 17 0 126.5 7.9 1.4X +HiveHasher 38 38 0 55.4 18.1 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Hash byte arrays with length 31: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Murmur3_x86_32 35 35 0 59.7 16.7 1.0X +xxHash 64-bit 30 30 0 69.3 14.4 1.2X +HiveHasher 48 48 0 43.6 22.9 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Hash byte arrays with length 95: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Murmur3_x86_32 79 80 0 26.4 37.9 1.0X +xxHash 64-bit 66 67 1 31.6 31.6 1.2X +HiveHasher 181 181 0 11.6 86.2 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Hash byte arrays with length 287: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Murmur3_x86_32 222 222 0 9.5 105.7 1.0X +xxHash 64-bit 111 111 0 18.9 52.9 2.0X +HiveHasher 608 608 1 3.5 289.7 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Hash byte arrays with length 1055: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Murmur3_x86_32 799 799 0 2.6 381.0 1.0X +xxHash 64-bit 282 282 0 7.4 134.4 2.8X +HiveHasher 2311 2311 0 0.9 1101.9 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Hash byte arrays with length 2079: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Murmur3_x86_32 1629 1635 8 1.3 776.9 1.0X +xxHash 64-bit 507 509 2 4.1 241.9 3.2X +HiveHasher 4588 4589 0 0.5 2187.9 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Hash byte arrays with length 8223: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Murmur3_x86_32 6254 6257 4 0.3 2982.3 1.0X +xxHash 64-bit 1866 1866 0 1.1 889.8 3.4X +HiveHasher 18213 18222 13 0.1 8684.8 0.3X + + diff --git a/sql/catalyst/benchmarks/HexBenchmark-jdk25-results.txt b/sql/catalyst/benchmarks/HexBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..f19e7b7b770b9 --- /dev/null +++ b/sql/catalyst/benchmarks/HexBenchmark-jdk25-results.txt @@ -0,0 +1,14 @@ +================================================================================================ +UnHex Comparison +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Cardinality 1000000: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Common Codecs 4772 4806 30 0.2 4771.8 1.0X +Java 4323 4339 17 0.2 4323.3 1.1X +Spark 3543 3550 12 0.3 3543.1 1.3X +Spark Binary 2692 2693 1 0.4 2692.3 1.8X + + diff --git a/sql/catalyst/benchmarks/InternalRowComparableWrapperBenchmark-jdk25-results.txt b/sql/catalyst/benchmarks/InternalRowComparableWrapperBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..f6605513454e7 --- /dev/null +++ b/sql/catalyst/benchmarks/InternalRowComparableWrapperBenchmark-jdk25-results.txt @@ -0,0 +1,7 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +internal row comparable wrapper: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +toSet 19 19 1 10.7 93.6 1.0X +mergePartitions 25 26 1 7.9 126.4 0.7X + diff --git a/sql/catalyst/benchmarks/SparkBloomFilterBenchmark-jdk25-results.txt b/sql/catalyst/benchmarks/SparkBloomFilterBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..ec4c02194d28f --- /dev/null +++ b/sql/catalyst/benchmarks/SparkBloomFilterBenchmark-jdk25-results.txt @@ -0,0 +1,300 @@ +================================================================================================ +Put Operation - Small Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Put Operation - 10000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +BloomFilterImpl V1 - 10000 0 0 0 24.7 40.5 1.0X +BloomFilterImplV2 - 10000 0 0 0 22.4 44.6 0.9X + + +================================================================================================ +Put Operation - Medium Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Put Operation - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +BloomFilterImpl V1 - 100000 5 5 0 20.2 49.4 1.0X +BloomFilterImplV2 - 100000 5 5 0 20.6 48.5 1.0X + + +================================================================================================ +Put Operation - Large Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Put Operation - 1000000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +BloomFilterImpl V1 - 1000000 55 55 0 18.3 54.6 1.0X +BloomFilterImplV2 - 1000000 55 55 0 18.3 54.7 1.0X + + +================================================================================================ +MightContain Operation - Small Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +MightContain Operation (Hit Rate: 50.0%) - 10000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 10000 0 0 0 39.1 25.6 1.0X +BloomFilterImplV2 - 10000 0 0 0 39.6 25.2 1.0X + + +================================================================================================ +MightContain Operation - Medium Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +MightContain Operation (Hit Rate: 50.0%) - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 3 3 0 36.7 27.3 1.0X +BloomFilterImplV2 - 100000 3 3 0 34.2 29.3 0.9X + + +================================================================================================ +MightContain Operation - Large Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +MightContain Operation (Hit Rate: 50.0%) - 1000000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 1000000 32 32 0 31.6 31.6 1.0X +BloomFilterImplV2 - 1000000 34 34 0 29.4 34.0 0.9X + + +================================================================================================ +FPP Impact on Put Operations +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Put Operation - 100000 items, FPP: 0.01: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +BloomFilterImpl V1 - 100000 6 7 0 15.4 64.9 1.0X +BloomFilterImplV2 - 100000 6 6 0 15.7 63.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Put Operation - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +BloomFilterImpl V1 - 100000 5 5 0 20.2 49.5 1.0X +BloomFilterImplV2 - 100000 5 5 0 20.6 48.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Put Operation - 100000 items, FPP: 0.05: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +BloomFilterImpl V1 - 100000 4 4 0 24.4 41.0 1.0X +BloomFilterImplV2 - 100000 4 4 0 24.5 40.9 1.0X + + +================================================================================================ +FPP Impact on Query Operations +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +MightContain Operation (Hit Rate: 50.0%) - 100000 items, FPP: 0.01: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 3 3 0 32.8 30.5 1.0X +BloomFilterImplV2 - 100000 3 3 0 30.5 32.8 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +MightContain Operation (Hit Rate: 50.0%) - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 3 3 0 36.7 27.3 1.0X +BloomFilterImplV2 - 100000 3 3 0 34.2 29.2 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +MightContain Operation (Hit Rate: 50.0%) - 100000 items, FPP: 0.05: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 3 3 0 39.3 25.4 1.0X +BloomFilterImplV2 - 100000 3 3 0 37.1 26.9 0.9X + + +================================================================================================ +Hit Rate Impact Analysis +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +MightContain Operation (Hit Rate: 10.0%) - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 3 3 0 32.0 31.2 1.0X +BloomFilterImplV2 - 100000 3 3 0 29.4 34.0 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +MightContain Operation (Hit Rate: 50.0%) - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 3 3 0 36.5 27.4 1.0X +BloomFilterImplV2 - 100000 3 3 0 34.2 29.2 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +MightContain Operation (Hit Rate: 90.0%) - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 2 2 0 43.1 23.2 1.0X +BloomFilterImplV2 - 100000 2 2 0 40.7 24.6 0.9X + + +================================================================================================ +Binary Put Operation - Small Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary PUT Operation - 10000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 10000 1 1 0 11.5 86.6 1.0X +BloomFilterImplV2 - 10000 1 1 0 10.2 97.8 0.9X + + +================================================================================================ +Binary Put Operation - Medium Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary PUT Operation - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +BloomFilterImpl V1 - 100000 9 9 0 10.7 93.1 1.0X +BloomFilterImplV2 - 100000 11 11 0 9.4 106.9 0.9X + + +================================================================================================ +Binary Put Operation - Large Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary PUT Operation - 1000000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 1000000 100 100 0 10.0 100.1 1.0X +BloomFilterImplV2 - 1000000 118 118 0 8.5 117.9 0.8X + + +================================================================================================ +Binary Query Operation - Small Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary Query Operation (Hit Rate: 50.0%) - 10000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 10000 1 1 0 16.9 59.0 1.0X +BloomFilterImplV2 - 10000 1 1 0 16.2 61.7 1.0X + + +================================================================================================ +Binary Query Operation - Medium Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary Query Operation (Hit Rate: 50.0%) - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 6 6 0 15.5 64.6 1.0X +BloomFilterImplV2 - 100000 7 7 0 14.8 67.4 1.0X + + +================================================================================================ +Binary Query Operation - Large Scale +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary Query Operation (Hit Rate: 50.0%) - 1000000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 1000000 70 70 0 14.3 69.7 1.0X +BloomFilterImplV2 - 1000000 76 76 0 13.2 75.9 0.9X + + +================================================================================================ +FPP Impact on Binary Put Operations +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary PUT Operation - 100000 items, FPP: 0.01: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +BloomFilterImpl V1 - 100000 11 11 0 9.1 109.9 1.0X +BloomFilterImplV2 - 100000 13 13 0 8.0 125.4 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary PUT Operation - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +BloomFilterImpl V1 - 100000 9 9 0 10.7 93.2 1.0X +BloomFilterImplV2 - 100000 11 11 0 9.4 106.7 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary PUT Operation - 100000 items, FPP: 0.05: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +BloomFilterImpl V1 - 100000 8 8 0 12.2 81.8 1.0X +BloomFilterImplV2 - 100000 9 9 0 10.6 94.2 0.9X + + +================================================================================================ +FPP Impact on Binary Query Operations +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary Query Operation (Hit Rate: 50.0%) - 100000 items, FPP: 0.01: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 7 7 0 14.6 68.3 1.0X +BloomFilterImplV2 - 100000 7 7 0 14.0 71.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary Query Operation (Hit Rate: 50.0%) - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 6 6 0 15.5 64.5 1.0X +BloomFilterImplV2 - 100000 7 7 0 14.9 67.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary Query Operation (Hit Rate: 50.0%) - 100000 items, FPP: 0.05: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 6 6 0 16.0 62.3 1.0X +BloomFilterImplV2 - 100000 6 6 0 15.7 63.8 1.0X + + +================================================================================================ +Hit Rate Impact on Binary Operations +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary Query Operation (Hit Rate: 10.0%) - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 7 7 0 15.3 65.4 1.0X +BloomFilterImplV2 - 100000 7 7 0 14.9 67.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary Query Operation (Hit Rate: 50.0%) - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 6 6 0 15.5 64.7 1.0X +BloomFilterImplV2 - 100000 7 7 0 14.9 67.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Binary Query Operation (Hit Rate: 90.0%) - 100000 items, FPP: 0.03: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------- +BloomFilterImpl V1 - 100000 6 6 0 15.7 63.6 1.0X +BloomFilterImplV2 - 100000 7 7 0 14.9 67.1 0.9X + + diff --git a/sql/catalyst/benchmarks/UnsafeProjectionBenchmark-jdk25-results.txt b/sql/catalyst/benchmarks/UnsafeProjectionBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..8ea2de901da3e --- /dev/null +++ b/sql/catalyst/benchmarks/UnsafeProjectionBenchmark-jdk25-results.txt @@ -0,0 +1,14 @@ +================================================================================================ +unsafe projection +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +unsafe projection: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +single long 1325 1325 0 202.7 4.9 1.0X +single nullable long 2427 2429 3 110.6 9.0 0.5X +7 primitive types 7476 7484 11 35.9 27.9 0.2X +7 nullable primitive types 10587 10608 29 25.4 39.4 0.1X + + diff --git a/sql/core/benchmarks/AggregateBenchmark-jdk25-results.txt b/sql/core/benchmarks/AggregateBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..e35dc1037bbc7 --- /dev/null +++ b/sql/core/benchmarks/AggregateBenchmark-jdk25-results.txt @@ -0,0 +1,148 @@ +================================================================================================ +aggregate without grouping +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +agg w/o group: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +agg w/o group wholestage off 43452 45977 3571 48.3 20.7 1.0X +agg w/o group wholestage on 2959 2964 4 708.7 1.4 14.7X + + +================================================================================================ +stat functions +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +stddev: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +stddev wholestage off 4555 4573 26 23.0 43.4 1.0X +stddev wholestage on 849 856 6 123.5 8.1 5.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +kurtosis: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +kurtosis wholestage off 27341 27358 24 3.8 260.7 1.0X +kurtosis wholestage on 947 951 6 110.8 9.0 28.9X + + +================================================================================================ +aggregate with linear keys +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Aggregate w keys: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +codegen = F 7630 8038 577 11.0 91.0 1.0X +codegen = T, hashmap = F 4040 4076 44 20.8 48.2 1.9X +codegen = T, row-based hashmap = T 1139 1179 67 73.7 13.6 6.7X +codegen = T, vectorized hashmap = T 781 786 5 107.4 9.3 9.8X + + +================================================================================================ +aggregate with randomized keys +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Aggregate w keys: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +codegen = F 6300 6378 111 13.3 75.1 1.0X +codegen = T, hashmap = F 3752 3810 51 22.4 44.7 1.7X +codegen = T, row-based hashmap = T 1712 1719 5 49.0 20.4 3.7X +codegen = T, vectorized hashmap = T 1179 1209 17 71.2 14.1 5.3X + + +================================================================================================ +aggregate with string key +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Aggregate w string key: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +codegen = F 2182 2239 81 9.6 104.0 1.0X +codegen = T, hashmap = F 1300 1308 11 16.1 62.0 1.7X +codegen = T, row-based hashmap = T 950 958 7 22.1 45.3 2.3X +codegen = T, vectorized hashmap = T 800 805 4 26.2 38.2 2.7X + + +================================================================================================ +aggregate with decimal key +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Aggregate w decimal key: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +codegen = F 2547 2647 142 8.2 121.4 1.0X +codegen = T, hashmap = F 1499 1525 36 14.0 71.5 1.7X +codegen = T, row-based hashmap = T 521 534 17 40.2 24.9 4.9X +codegen = T, vectorized hashmap = T 320 324 2 65.5 15.3 8.0X + + +================================================================================================ +aggregate with multiple key types +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Aggregate w multiple keys: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +codegen = F 4153 4206 74 5.0 198.1 1.0X +codegen = T, hashmap = F 1962 1982 29 10.7 93.5 2.1X +codegen = T, row-based hashmap = T 1606 1621 21 13.1 76.6 2.6X +codegen = T, vectorized hashmap = T 1528 1528 0 13.7 72.8 2.7X + + +================================================================================================ +max function bytecode size of wholestagecodegen +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +max function bytecode size: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +codegen = F 408 428 33 1.6 622.9 1.0X +codegen = T, hugeMethodLimit = 10000 131 144 14 5.0 199.9 3.1X +codegen = T, hugeMethodLimit = 1500 129 139 11 5.1 197.0 3.2X + + +================================================================================================ +cube +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +cube: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +cube wholestage off 1781 1814 46 2.9 339.8 1.0X +cube wholestage on 909 921 10 5.8 173.3 2.0X + + +================================================================================================ +hash and BytesToBytesMap +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +BytesToBytesMap: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +UnsafeRowhash 116 116 0 181.5 5.5 1.0X +murmur3 hash 47 47 0 447.7 2.2 2.5X +fast hash 39 40 0 531.3 1.9 2.9X +arrayEqual 121 121 0 173.3 5.8 1.0X +Java HashMap (Long) 67 82 11 314.5 3.2 1.7X +Java HashMap (two ints) 83 86 3 252.7 4.0 1.4X +Java HashMap (UnsafeRow) 471 472 1 44.5 22.5 0.2X +LongToUnsafeRowMap (opt=false) 361 361 1 58.1 17.2 0.3X +LongToUnsafeRowMap (opt=true) 63 67 5 332.2 3.0 1.8X +BytesToBytesMap (off Heap) 437 443 5 48.0 20.8 0.3X +BytesToBytesMap (on Heap) 450 454 4 46.6 21.4 0.3X +Aggregate HashMap 40 40 0 522.2 1.9 2.9X + + diff --git a/sql/core/benchmarks/AnsiIntervalSortBenchmark-jdk25-results.txt b/sql/core/benchmarks/AnsiIntervalSortBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..dcb6b624636a6 --- /dev/null +++ b/sql/core/benchmarks/AnsiIntervalSortBenchmark-jdk25-results.txt @@ -0,0 +1,28 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +year month interval one column: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------- +year month interval one column enable radix 24793 25067 239 4.0 247.9 1.0X +year month interval one column disable radix 38112 38130 25 2.6 381.1 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +year month interval two columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------- +year month interval two columns enable radix 38273 38512 383 2.6 382.7 1.0X +year month interval two columns disable radix 39048 39138 106 2.6 390.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +day time interval one columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +day time interval one columns enable radix 23545 23935 487 4.2 235.5 1.0X +day time interval one columns disable radix 37507 38095 535 2.7 375.1 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +day time interval two columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +day time interval two columns enable radix 38846 39041 172 2.6 388.5 1.0X +day time interval two columns disable radix 38010 38103 102 2.6 380.1 1.0X + diff --git a/sql/core/benchmarks/Base64Benchmark-jdk25-results.txt b/sql/core/benchmarks/Base64Benchmark-jdk25-results.txt new file mode 100644 index 0000000000000..4734c0ca1427f --- /dev/null +++ b/sql/core/benchmarks/Base64Benchmark-jdk25-results.txt @@ -0,0 +1,56 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +encode for 1: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java 1836 1877 37 10.9 91.8 1.0X +apache 11472 11483 17 1.7 573.6 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +encode for 3: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java 2244 2256 11 8.9 112.2 1.0X +apache 12196 12260 64 1.6 609.8 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +encode for 5: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java 2683 2689 5 7.5 134.2 1.0X +apache 13660 13685 35 1.5 683.0 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +encode for 7: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java 2571 2577 6 7.8 128.5 1.0X +apache 14474 14501 26 1.4 723.7 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +decode for 1: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java 3115 3125 8 6.4 155.7 1.0X +apache 12323 12355 33 1.6 616.2 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +decode for 3: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java 3710 3714 4 5.4 185.5 1.0X +apache 14185 14206 23 1.4 709.3 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +decode for 5: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java 4410 4413 4 4.5 220.5 1.0X +apache 15353 15401 46 1.3 767.6 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +decode for 7: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +java 4403 4412 8 4.5 220.2 1.0X +apache 16462 16504 39 1.2 823.1 0.3X + diff --git a/sql/core/benchmarks/BloomFilterBenchmark-jdk25-results.txt b/sql/core/benchmarks/BloomFilterBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..905f71020d6a8 --- /dev/null +++ b/sql/core/benchmarks/BloomFilterBenchmark-jdk25-results.txt @@ -0,0 +1,196 @@ +================================================================================================ +ORC Write +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without bloom filter 7745 7780 49 12.9 77.4 1.0X +With bloom filter 9525 9546 30 10.5 95.2 0.8X + + +================================================================================================ +ORC Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without bloom filter, blocksize: 2097152 858 873 13 116.5 8.6 1.0X +With bloom filter, blocksize: 2097152 584 595 7 171.2 5.8 1.5X + + +================================================================================================ +ORC Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without bloom filter, blocksize: 4194304 825 830 4 121.2 8.3 1.0X +With bloom filter, blocksize: 4194304 560 590 24 178.7 5.6 1.5X + + +================================================================================================ +ORC Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without bloom filter, blocksize: 6291456 816 837 30 122.5 8.2 1.0X +With bloom filter, blocksize: 6291456 587 607 16 170.5 5.9 1.4X + + +================================================================================================ +ORC Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without bloom filter, blocksize: 8388608 812 819 10 123.2 8.1 1.0X +With bloom filter, blocksize: 8388608 581 589 8 172.2 5.8 1.4X + + +================================================================================================ +ORC Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Without bloom filter, blocksize: 12582912 809 819 10 123.6 8.1 1.0X +With bloom filter, blocksize: 12582912 574 586 11 174.3 5.7 1.4X + + +================================================================================================ +ORC Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Without bloom filter, blocksize: 16777216 793 806 12 126.1 7.9 1.0X +With bloom filter, blocksize: 16777216 553 583 21 181.0 5.5 1.4X + + +================================================================================================ +ORC Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Without bloom filter, blocksize: 33554432 790 806 15 126.6 7.9 1.0X +With bloom filter, blocksize: 33554432 527 529 2 189.8 5.3 1.5X + + +================================================================================================ +Parquet Write +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +Without bloom filter 10424 10428 6 9.6 104.2 1.0X +With bloom filter 18761 18778 23 5.3 187.6 0.6X +With adaptive bloom filter & 3 candidates 18770 18850 113 5.3 187.7 0.6X +With adaptive bloom filter & 5 candidates 18780 18820 56 5.3 187.8 0.6X +With adaptive bloom filter & 9 candidates 18614 18691 109 5.4 186.1 0.6X +With adaptive bloom filter & 15 candidates 18615 18630 21 5.4 186.1 0.6X + + +================================================================================================ +Parquet Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without bloom filter, blocksize: 2097152 388 400 10 257.4 3.9 1.0X +With bloom filter, blocksize: 2097152 173 186 12 579.6 1.7 2.3X + + +================================================================================================ +Parquet Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without bloom filter, blocksize: 4194304 380 391 13 263.5 3.8 1.0X +With bloom filter, blocksize: 4194304 122 128 4 819.1 1.2 3.1X + + +================================================================================================ +Parquet Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without bloom filter, blocksize: 6291456 369 373 3 270.8 3.7 1.0X +With bloom filter, blocksize: 6291456 144 154 4 693.3 1.4 2.6X + + +================================================================================================ +Parquet Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without bloom filter, blocksize: 8388608 363 376 9 275.6 3.6 1.0X +With bloom filter, blocksize: 8388608 121 134 11 825.0 1.2 3.0X + + +================================================================================================ +Parquet Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Without bloom filter, blocksize: 12582912 361 370 6 277.0 3.6 1.0X +With bloom filter, blocksize: 12582912 337 340 3 296.6 3.4 1.1X + + +================================================================================================ +Parquet Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Without bloom filter, blocksize: 16777216 388 408 20 257.9 3.9 1.0X +With bloom filter, blocksize: 16777216 355 370 8 282.0 3.5 1.1X + + +================================================================================================ +Parquet Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read a row from 100M rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Without bloom filter, blocksize: 33554432 376 382 4 266.2 3.8 1.0X +With bloom filter, blocksize: 33554432 382 389 4 261.6 3.8 1.0X + + diff --git a/sql/core/benchmarks/BuiltInDataSourceWriteBenchmark-jdk25-results.txt b/sql/core/benchmarks/BuiltInDataSourceWriteBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..9f7fb8ea90d7b --- /dev/null +++ b/sql/core/benchmarks/BuiltInDataSourceWriteBenchmark-jdk25-results.txt @@ -0,0 +1,70 @@ +================================================================================================ +Parquet writer benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Parquet(PARQUET_1_0) writer benchmark: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Output Single Int Column 1788 1859 101 8.8 113.7 1.0X +Output Single Double Column 1760 1773 18 8.9 111.9 1.0X +Output Int and String Column 4255 4258 4 3.7 270.5 0.4X +Output Partitions 3224 3265 57 4.9 205.0 0.6X +Output Buckets 4640 4721 114 3.4 295.0 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Parquet(PARQUET_2_0) writer benchmark: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Output Single Int Column 1892 1927 49 8.3 120.3 1.0X +Output Single Double Column 1801 1808 11 8.7 114.5 1.1X +Output Int and String Column 4344 4347 4 3.6 276.2 0.4X +Output Partitions 3354 3375 30 4.7 213.3 0.6X +Output Buckets 4450 4462 17 3.5 282.9 0.4X + + +================================================================================================ +ORC writer benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +ORC writer benchmark: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Output Single Int Column 987 991 7 15.9 62.7 1.0X +Output Single Double Column 1516 1524 10 10.4 96.4 0.7X +Output Int and String Column 3575 3587 17 4.4 227.3 0.3X +Output Partitions 2365 2369 6 6.7 150.3 0.4X +Output Buckets 3368 3569 283 4.7 214.2 0.3X + + +================================================================================================ +JSON writer benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +JSON writer benchmark: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Output Single Int Column 1568 1579 15 10.0 99.7 1.0X +Output Single Double Column 2345 2347 3 6.7 149.1 0.7X +Output Int and String Column 3541 3559 25 4.4 225.2 0.4X +Output Partitions 3120 3121 1 5.0 198.4 0.5X +Output Buckets 4100 4111 16 3.8 260.7 0.4X + + +================================================================================================ +CSV writer benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +CSV writer benchmark: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Output Single Int Column 2705 2722 25 5.8 172.0 1.0X +Output Single Double Column 3398 3400 3 4.6 216.0 0.8X +Output Int and String Column 4619 4619 0 3.4 293.6 0.6X +Output Partitions 4120 4157 52 3.8 261.9 0.7X +Output Buckets 5451 5459 11 2.9 346.6 0.5X + + diff --git a/sql/core/benchmarks/ByteArrayBenchmark-jdk25-results.txt b/sql/core/benchmarks/ByteArrayBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..470b123c7ad85 --- /dev/null +++ b/sql/core/benchmarks/ByteArrayBenchmark-jdk25-results.txt @@ -0,0 +1,27 @@ +================================================================================================ +byte array comparisons +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Byte Array compareTo: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +2-7 byte 259 291 16 252.7 4.0 1.0X +8-16 byte 343 383 53 191.2 5.2 0.8X +16-32 byte 347 348 1 189.1 5.3 0.7X +512-1024 byte 467 470 1 140.2 7.1 0.6X +512 byte slow 1935 1952 11 33.9 29.5 0.1X +2-7 byte 278 279 1 235.6 4.2 0.9X + + +================================================================================================ +byte array equals +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Byte Array equals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Byte Array equals 1077 1080 2 148.5 6.7 1.0X + + diff --git a/sql/core/benchmarks/CSVBenchmark-jdk25-results.txt b/sql/core/benchmarks/CSVBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..a072b79cb981a --- /dev/null +++ b/sql/core/benchmarks/CSVBenchmark-jdk25-results.txt @@ -0,0 +1,77 @@ +================================================================================================ +Benchmark to measure CSV read/write performance +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Parsing quoted values: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +One quoted string 24142 24354 347 0.0 482846.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Wide rows with 1000 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Select 1000 columns 54506 54865 537 0.0 54506.2 1.0X +Select 100 columns 20120 20224 127 0.0 20119.6 2.7X +Select one column 16768 16835 65 0.1 16768.1 3.3X +count() 3309 3350 63 0.3 3308.7 16.5X +Select 100 columns, one bad input field 24294 24322 25 0.0 24294.1 2.2X +Select 100 columns, corrupt record field 27414 27553 128 0.0 27414.5 2.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Count a dataset with 10 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Select 10 columns + count() 10745 10768 23 0.9 1074.5 1.0X +Select 1 column + count() 7639 7670 27 1.3 763.9 1.4X +count() 1825 1833 9 5.5 182.5 5.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write dates and timestamps: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Create a dataset of timestamps 816 827 18 12.3 81.6 1.0X +to_csv(timestamp) 5684 5774 116 1.8 568.4 0.1X +write timestamps to files 6362 6377 13 1.6 636.2 0.1X +Create a dataset of dates 918 929 13 10.9 91.8 0.9X +to_csv(date) 4380 4393 12 2.3 438.0 0.2X +write dates to files 4561 4595 30 2.2 456.1 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read dates and timestamps: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------------------------- +read timestamp text from files 1274 1277 3 7.8 127.4 1.0X +read timestamps from files 11382 11403 30 0.9 1138.2 0.1X +infer timestamps from files 22670 22804 131 0.4 2267.0 0.1X +read date text from files 1159 1173 13 8.6 115.9 1.1X +read date from files 11220 11232 10 0.9 1122.0 0.1X +infer date from files 22956 23076 108 0.4 2295.6 0.1X +timestamp strings 1114 1119 6 9.0 111.4 1.1X +parse timestamps from Dataset[String] 12416 12434 17 0.8 1241.6 0.1X +infer timestamps from Dataset[String] 23223 23341 102 0.4 2322.3 0.1X +date strings 1527 1533 7 6.6 152.7 0.8X +parse dates from Dataset[String] 12473 12490 15 0.8 1247.3 0.1X +from_csv(timestamp) 10490 10511 19 1.0 1049.0 0.1X +from_csv(date) 11006 11026 30 0.9 1100.6 0.1X +infer error timestamps from Dataset[String] with default format 14173 14258 74 0.7 1417.3 0.1X +infer error timestamps from Dataset[String] with user-provided format 14214 14230 18 0.7 1421.4 0.1X +infer error timestamps from Dataset[String] with legacy format 14289 14317 26 0.7 1428.9 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Filters pushdown: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +w/o filters 3421 3431 10 0.0 34206.0 1.0X +pushdown disabled 3360 3405 55 0.0 33598.8 1.0X +w/ filters 774 778 5 0.1 7739.4 4.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Interval: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Read as Intervals 722 725 3 0.4 2407.0 1.0X +Read Raw Strings 329 332 4 0.9 1097.1 2.2X + + diff --git a/sql/core/benchmarks/CharVarcharBenchmark-jdk25-results.txt b/sql/core/benchmarks/CharVarcharBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..b9127384f6fb9 --- /dev/null +++ b/sql/core/benchmarks/CharVarcharBenchmark-jdk25-results.txt @@ -0,0 +1,122 @@ +================================================================================================ +Char Varchar Write Side Perf w/o Tailing Spaces +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 5: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 5 6305 6582 259 6.3 157.6 1.0X +write char with length 5 9873 9896 28 4.1 246.8 0.6X +write varchar with length 5 6991 7161 154 5.7 174.8 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 10: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 10 3490 3494 6 5.7 174.5 1.0X +write char with length 10 5850 5859 8 3.4 292.5 0.6X +write varchar with length 10 3512 3536 23 5.7 175.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 20: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 20 1651 1664 13 6.1 165.1 1.0X +write char with length 20 4203 4253 85 2.4 420.3 0.4X +write varchar with length 20 1831 1853 18 5.5 183.1 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 40: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 40 921 928 7 5.4 184.3 1.0X +write char with length 40 3250 3258 8 1.5 650.0 0.3X +write varchar with length 40 984 991 7 5.1 196.8 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 60: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 60 659 663 6 5.1 197.7 1.0X +write char with length 60 3004 3009 4 1.1 901.3 0.2X +write varchar with length 60 675 680 9 4.9 202.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 80: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 80 479 480 2 5.2 191.5 1.0X +write char with length 80 2850 2852 3 0.9 1140.0 0.2X +write varchar with length 80 516 522 8 4.8 206.5 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 100: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 100 428 431 2 4.7 214.2 1.0X +write char with length 100 2776 2787 11 0.7 1388.2 0.2X +write varchar with length 100 453 457 4 4.4 226.3 0.9X + + +================================================================================================ +Char Varchar Write Side Perf w/ Tailing Spaces +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 5: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 5 8483 8538 48 4.7 212.1 1.0X +write char with length 5 9984 9999 24 4.0 249.6 0.8X +write varchar with length 5 10247 10277 30 3.9 256.2 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 10: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 10 4243 4263 20 4.7 212.1 1.0X +write char with length 10 6183 6209 23 3.2 309.2 0.7X +write varchar with length 10 6360 6399 38 3.1 318.0 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 20: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 20 2575 2590 18 3.9 257.5 1.0X +write char with length 20 4240 4262 20 2.4 424.0 0.6X +write varchar with length 20 4383 4396 11 2.3 438.3 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 40: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 40 1653 1655 2 3.0 330.6 1.0X +write char with length 40 3293 3304 17 1.5 658.6 0.5X +write varchar with length 40 3315 3321 5 1.5 663.0 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 60: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 60 1423 1428 4 2.3 427.0 1.0X +write char with length 60 2978 2991 18 1.1 893.3 0.5X +write varchar with length 60 3055 3056 2 1.1 916.4 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 80: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 80 1130 1147 16 2.2 452.0 1.0X +write char with length 80 2819 2820 1 0.9 1127.5 0.4X +write varchar with length 80 2819 2838 24 0.9 1127.7 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write with length 100: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +write string with length 100 1037 1052 13 1.9 518.6 1.0X +write char with length 100 2715 2728 12 0.7 1357.5 0.4X +write varchar with length 100 2744 2761 15 0.7 1371.8 0.4X + + diff --git a/sql/core/benchmarks/CollationBenchmark-jdk25-results.txt b/sql/core/benchmarks/CollationBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..1f9e9763c3632 --- /dev/null +++ b/sql/core/benchmarks/CollationBenchmark-jdk25-results.txt @@ -0,0 +1,88 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - equalsFunction: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +-------------------------------------------------------------------------------------------------------------------------- +UTF8_BINARY 2672 2673 2 0.0 26717.0 1.0X +UTF8_LCASE 3902 3902 0 0.0 39024.8 1.5X +UNICODE 17900 17918 26 0.0 178997.1 6.7X +UNICODE_CI 17617 17632 21 0.0 176167.4 6.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - compareFunction: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +--------------------------------------------------------------------------------------------------------------------------- +UTF8_BINARY 1806 1808 2 0.1 18064.4 1.0X +UTF8_LCASE 3891 3891 0 0.0 38910.2 2.2X +UNICODE 17894 17922 39 0.0 178937.5 9.9X +UNICODE_CI 17650 17689 55 0.0 176502.1 9.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - hashFunction: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +------------------------------------------------------------------------------------------------------------------------ +UTF8_BINARY 12122 12124 2 0.0 121222.5 1.0X +UTF8_LCASE 18710 18714 6 0.0 187103.9 1.5X +UNICODE 104253 104256 4 0.0 1042531.5 8.6X +UNICODE_CI 142640 142664 33 0.0 1426401.4 11.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - contains: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +------------------------------------------------------------------------------------------------------------------------ +UTF8_BINARY 2455 2456 2 0.0 24547.2 1.0X +UTF8_LCASE 16158 16160 2 0.0 161582.7 6.6X +UNICODE 310700 310973 386 0.0 3107002.0 126.6X +UNICODE_CI 318729 319323 839 0.0 3187290.7 129.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - startsWith: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +------------------------------------------------------------------------------------------------------------------------ +UTF8_BINARY 2110 2111 1 0.0 21101.9 1.0X +UTF8_LCASE 13327 13332 7 0.0 133272.1 6.3X +UNICODE 315226 315289 88 0.0 3152262.8 149.4X +UNICODE_CI 322243 322538 417 0.0 3222425.8 152.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - endsWith: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +------------------------------------------------------------------------------------------------------------------------ +UTF8_BINARY 2116 2138 31 0.0 21164.8 1.0X +UTF8_LCASE 13535 13540 6 0.0 135349.5 6.4X +UNICODE 332132 332492 509 0.0 3321319.3 156.9X +UNICODE_CI 333198 333653 643 0.0 3331981.5 157.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - initCap using impl execICU: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +-------------------------------------------------------------------------------------------------------------------------------------- +UNICODE 351 352 1 0.3 3514.1 1.0X +UNICODE_CI 351 353 2 0.3 3511.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - initCap using impl execBinaryICU: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +-------------------------------------------------------------------------------------------------------------------------------------------- +UTF8_BINARY 593 594 1 0.2 5926.9 1.0X +UTF8_LCASE 593 594 1 0.2 5930.5 1.0X +UNICODE 592 593 1 0.2 5922.6 1.0X +UNICODE_CI 593 593 1 0.2 5926.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - initCap using impl execBinary: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +----------------------------------------------------------------------------------------------------------------------------------------- +UTF8_BINARY 169 170 0 0.6 1690.4 1.0X +UTF8_LCASE 169 169 0 0.6 1685.8 1.0X +UNICODE 168 169 1 0.6 1683.5 1.0X +UNICODE_CI 168 169 1 0.6 1684.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - initCap using impl execLowercase: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +-------------------------------------------------------------------------------------------------------------------------------------------- +UTF8_BINARY 351 351 1 0.3 3506.7 1.0X +UTF8_LCASE 351 352 2 0.3 3509.4 1.0X +UNICODE 351 351 0 0.3 3506.9 1.0X +UNICODE_CI 351 352 1 0.3 3510.4 1.0X + diff --git a/sql/core/benchmarks/CollationNonASCIIBenchmark-jdk25-results.txt b/sql/core/benchmarks/CollationNonASCIIBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..99db117129fac --- /dev/null +++ b/sql/core/benchmarks/CollationNonASCIIBenchmark-jdk25-results.txt @@ -0,0 +1,88 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - equalsFunction: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +-------------------------------------------------------------------------------------------------------------------------- +UTF8_BINARY 158 158 0 0.3 3943.1 1.0X +UTF8_LCASE 7179 7186 10 0.0 179487.5 45.5X +UNICODE 5040 5041 2 0.0 126001.2 32.0X +UNICODE_CI 5124 5127 4 0.0 128108.7 32.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - compareFunction: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +--------------------------------------------------------------------------------------------------------------------------- +UTF8_BINARY 528 529 2 0.1 13194.5 1.0X +UTF8_LCASE 7432 7433 2 0.0 185789.3 14.1X +UNICODE 5450 5459 13 0.0 136237.7 10.3X +UNICODE_CI 5390 5392 2 0.0 134754.7 10.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - hashFunction: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +------------------------------------------------------------------------------------------------------------------------ +UTF8_BINARY 1603 1605 2 0.0 40085.0 1.0X +UTF8_LCASE 5857 5858 0 0.0 146436.7 3.7X +UNICODE 19992 19993 1 0.0 499803.9 12.5X +UNICODE_CI 26339 26352 19 0.0 658477.2 16.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - contains: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +------------------------------------------------------------------------------------------------------------------------ +UTF8_BINARY 613 614 1 0.1 15332.3 1.0X +UTF8_LCASE 10629 10630 2 0.0 265724.6 17.3X +UNICODE 58338 58353 20 0.0 1458460.0 95.1X +UNICODE_CI 58619 58622 5 0.0 1465466.5 95.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - startsWith: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +------------------------------------------------------------------------------------------------------------------------ +UTF8_BINARY 297 298 0 0.1 7434.8 1.0X +UTF8_LCASE 5542 5543 1 0.0 138545.3 18.6X +UNICODE 57950 58089 197 0.0 1448737.8 194.9X +UNICODE_CI 58980 59129 211 0.0 1474493.1 198.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - endsWith: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +------------------------------------------------------------------------------------------------------------------------ +UTF8_BINARY 281 282 0 0.1 7034.1 1.0X +UTF8_LCASE 6623 6625 3 0.0 165576.2 23.5X +UNICODE 65126 65216 128 0.0 1628147.7 231.5X +UNICODE_CI 64223 64248 36 0.0 1605563.0 228.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - initCap using impl execICU: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +-------------------------------------------------------------------------------------------------------------------------------------- +UNICODE 202 202 0 0.2 5042.2 1.0X +UNICODE_CI 204 205 1 0.2 5105.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - initCap using impl execBinaryICU: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +-------------------------------------------------------------------------------------------------------------------------------------------- +UTF8_BINARY 317 318 0 0.1 7934.8 1.0X +UTF8_LCASE 317 318 0 0.1 7935.0 1.0X +UNICODE 317 318 1 0.1 7931.5 1.0X +UNICODE_CI 317 318 0 0.1 7937.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - initCap using impl execBinary: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +----------------------------------------------------------------------------------------------------------------------------------------- +UTF8_BINARY 86 87 0 0.5 2155.3 1.0X +UTF8_LCASE 87 88 4 0.5 2170.7 1.0X +UNICODE 87 87 0 0.5 2164.6 1.0X +UNICODE_CI 86 87 0 0.5 2155.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collation unit benchmarks - initCap using impl execLowercase: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative time +-------------------------------------------------------------------------------------------------------------------------------------------- +UTF8_BINARY 202 203 1 0.2 5057.3 1.0X +UTF8_LCASE 203 204 0 0.2 5079.1 1.0X +UNICODE 202 203 1 0.2 5057.1 1.0X +UNICODE_CI 202 203 1 0.2 5061.9 1.0X + diff --git a/sql/core/benchmarks/ColumnarBatchBenchmark-jdk25-results.txt b/sql/core/benchmarks/ColumnarBatchBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..c5b65b2af90d8 --- /dev/null +++ b/sql/core/benchmarks/ColumnarBatchBenchmark-jdk25-results.txt @@ -0,0 +1,59 @@ +================================================================================================ +Int Read/Write +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Int Read/Write: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Java Array 51 52 0 6382.4 0.2 1.0X +ByteBuffer Unsafe 462 462 1 709.8 1.4 0.1X +ByteBuffer API 555 556 1 590.0 1.7 0.1X +DirectByteBuffer 378 378 1 867.2 1.2 0.1X +Unsafe Buffer 155 157 6 2120.4 0.5 0.3X +Column(on heap) 52 52 0 6308.6 0.2 1.0X +Column(off heap) 155 155 0 2119.6 0.5 0.3X +Column(off heap direct) 155 155 0 2118.6 0.5 0.3X +UnsafeRow (on heap) 224 225 1 1463.1 0.7 0.2X +UnsafeRow (off heap) 325 326 1 1007.2 1.0 0.2X +Column On Heap Append 423 423 1 775.5 1.3 0.1X + + +================================================================================================ +Boolean Read/Write +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Boolean Read/Write: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Bitset 392 393 1 855.1 1.2 1.0X +Byte Array 250 250 0 1340.7 0.7 1.6X + + +================================================================================================ +String Read/Write +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +String Read/Write: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +On Heap 183 184 0 89.6 11.2 1.0X +Off Heap 367 387 14 44.7 22.4 0.5X + + +================================================================================================ +Array Vector Read +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Array Vector Read: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +On Heap Read Size Only 84 84 0 1956.8 0.5 1.0X +Off Heap Read Size Only 289 289 0 567.4 1.8 0.3X +On Heap Read Elements 1432 1435 4 114.4 8.7 0.1X +Off Heap Read Elements 2851 2851 0 57.5 17.4 0.0X + + diff --git a/sql/core/benchmarks/CompressionSchemeBenchmark-jdk25-results.txt b/sql/core/benchmarks/CompressionSchemeBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..5a338c685228a --- /dev/null +++ b/sql/core/benchmarks/CompressionSchemeBenchmark-jdk25-results.txt @@ -0,0 +1,137 @@ +================================================================================================ +Compression Scheme Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +BOOLEAN Encode: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough(1.000) 1 1 0 49078.6 0.0 1.0X +RunLengthEncoding(2.487) 898 901 3 74.7 13.4 0.0X +BooleanBitSet(0.125) 287 287 0 233.6 4.3 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +BOOLEAN Decode: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough 0 0 0 5563659.8 0.0 1.0X +RunLengthEncoding 534 535 1 125.6 8.0 0.0X +BooleanBitSet 666 667 2 100.8 9.9 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +SHORT Encode (Lower Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough(1.000) 3 3 0 23078.1 0.0 1.0X +RunLengthEncoding(1.498) 1411 1411 0 47.6 21.0 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +SHORT Decode (Lower Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough 731 731 0 91.8 10.9 1.0X +RunLengthEncoding 1080 1080 1 62.2 16.1 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +SHORT Encode (Higher Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough(1.000) 3 3 0 23387.5 0.0 1.0X +RunLengthEncoding(2.002) 1241 1242 2 54.1 18.5 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +SHORT Decode (Higher Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough 690 690 1 97.3 10.3 1.0X +RunLengthEncoding 999 1000 1 67.1 14.9 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +INT Encode (Lower Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough(1.000) 6 6 0 11640.5 0.1 1.0X +RunLengthEncoding(0.997) 1068 1069 1 62.8 15.9 0.0X +DictionaryEncoding(0.500) 543 544 2 123.5 8.1 0.0X +IntDelta(0.250) 137 138 1 490.0 2.0 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +INT Decode (Lower Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough 773 774 0 86.8 11.5 1.0X +RunLengthEncoding 1245 1246 2 53.9 18.6 0.6X +DictionaryEncoding 710 711 0 94.5 10.6 1.1X +IntDelta 668 669 1 100.4 10.0 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +INT Encode (Higher Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough(1.000) 6 6 0 11043.2 0.1 1.0X +RunLengthEncoding(1.331) 1090 1115 35 61.6 16.2 0.0X +DictionaryEncoding(0.501) 544 544 0 123.4 8.1 0.0X +IntDelta(0.250) 110 111 0 607.7 1.6 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +INT Decode (Higher Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough 711 727 21 94.4 10.6 1.0X +RunLengthEncoding 1191 1193 3 56.4 17.7 0.6X +DictionaryEncoding 710 711 1 94.5 10.6 1.0X +IntDelta 668 668 0 100.5 10.0 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +LONG Encode (Lower Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough(1.000) 13 14 0 5016.4 0.2 1.0X +RunLengthEncoding(0.748) 1055 1055 1 63.6 15.7 0.0X +DictionaryEncoding(0.250) 567 567 1 118.4 8.4 0.0X +LongDelta(0.125) 111 111 0 605.5 1.7 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +LONG Decode (Lower Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough 900 900 0 74.6 13.4 1.0X +RunLengthEncoding 1224 1226 3 54.8 18.2 0.7X +DictionaryEncoding 794 795 1 84.5 11.8 1.1X +LongDelta 689 689 0 97.4 10.3 1.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +LONG Encode (Higher Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough(1.000) 13 14 0 5018.6 0.2 1.0X +RunLengthEncoding(1.001) 1069 1070 2 62.8 15.9 0.0X +DictionaryEncoding(0.251) 567 567 0 118.4 8.4 0.0X +LongDelta(0.125) 111 111 0 606.0 1.7 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +LONG Decode (Higher Skew): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough 860 901 35 78.0 12.8 1.0X +RunLengthEncoding 1206 1209 4 55.6 18.0 0.7X +DictionaryEncoding 732 733 1 91.6 10.9 1.2X +LongDelta 690 690 1 97.3 10.3 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +STRING Encode: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough(1.000) 20 20 0 3346.6 0.3 1.0X +RunLengthEncoding(0.890) 1968 1969 1 34.1 29.3 0.0X +DictionaryEncoding(0.167) 1711 1711 0 39.2 25.5 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +STRING Decode: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +PassThrough 1655 1655 1 40.6 24.7 1.0X +RunLengthEncoding 2229 2232 4 30.1 33.2 0.7X +DictionaryEncoding 1934 1936 3 34.7 28.8 0.9X + + diff --git a/sql/core/benchmarks/ConstantColumnVectorBenchmark-jdk25-results.txt b/sql/core/benchmarks/ConstantColumnVectorBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..16b0073e085b0 --- /dev/null +++ b/sql/core/benchmarks/ConstantColumnVectorBenchmark-jdk25-results.txt @@ -0,0 +1,280 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write with StringType, row length = 1: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 1 1 0 421935.7 0.0 1.0X +OnHeapColumnVector 2625 2626 1 156.0 6.4 0.0X +OffHeapColumnVector 3886 3888 3 105.4 9.5 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write with StringType, row length = 5: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 1 1 0 518462.6 0.0 1.0X +OnHeapColumnVector 3441 3447 8 119.0 8.4 0.0X +OffHeapColumnVector 4323 4323 1 94.8 10.6 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write with StringType, row length = 10: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 1 1 0 518515.8 0.0 1.0X +OnHeapColumnVector 3930 3942 16 104.2 9.6 0.0X +OffHeapColumnVector 4660 4661 0 87.9 11.4 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write with StringType, row length = 15: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 1 1 0 518410.8 0.0 1.0X +OnHeapColumnVector 3629 3632 5 112.9 8.9 0.0X +OffHeapColumnVector 4321 4321 1 94.8 10.5 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write with StringType, row length = 20: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 1 1 0 519939.5 0.0 1.0X +OnHeapColumnVector 3751 3755 6 109.2 9.2 0.0X +OffHeapColumnVector 4469 4470 1 91.7 10.9 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write with StringType, row length = 30: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 1 1 0 518417.4 0.0 1.0X +OnHeapColumnVector 4108 4108 0 99.7 10.0 0.0X +OffHeapColumnVector 4739 4739 1 86.4 11.6 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write with IntegerType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 1 1 0 474528.8 0.0 1.0X +OnHeapColumnVector 16 16 0 25172.2 0.0 0.1X +OffHeapColumnVector 65 65 0 6287.6 0.2 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write with LongType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 1 1 0 632702.2 0.0 1.0X +OnHeapColumnVector 35 35 0 11766.6 0.1 0.0X +OffHeapColumnVector 67 69 3 6097.4 0.2 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write with FloatType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 1 1 0 530953.0 0.0 1.0X +OnHeapColumnVector 16 16 0 25019.3 0.0 0.0X +OffHeapColumnVector 128 128 0 3198.2 0.3 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write with DoubleType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 1 1 0 474066.4 0.0 1.0X +OnHeapColumnVector 35 35 0 11655.0 0.1 0.0X +OffHeapColumnVector 129 129 0 3171.7 0.3 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test read with StringType, row length = 1: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 324 325 1 1263.3 0.8 1.0X +OnHeapColumnVector 99 99 0 4156.2 0.2 3.3X +OffHeapColumnVector 3421 3422 2 119.7 8.4 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test read with StringType, row length = 5: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 472 474 2 867.0 1.2 1.0X +OnHeapColumnVector 3380 3393 19 121.2 8.3 0.1X +OffHeapColumnVector 3434 3435 2 119.3 8.4 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test read with StringType, row length = 10: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 473 475 2 866.7 1.2 1.0X +OnHeapColumnVector 3380 3381 1 121.2 8.3 0.1X +OffHeapColumnVector 3434 3445 15 119.3 8.4 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test read with StringType, row length = 15: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 470 471 1 871.3 1.1 1.0X +OnHeapColumnVector 3385 3385 1 121.0 8.3 0.1X +OffHeapColumnVector 3432 3435 4 119.3 8.4 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test read with StringType, row length = 20: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 465 469 4 881.1 1.1 1.0X +OnHeapColumnVector 3385 3386 1 121.0 8.3 0.1X +OffHeapColumnVector 3426 3430 6 119.6 8.4 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test read with StringType, row length = 30: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 475 476 1 863.1 1.2 1.0X +OnHeapColumnVector 3377 3377 1 121.3 8.2 0.1X +OffHeapColumnVector 3430 3432 2 119.4 8.4 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test read with IntegerType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 0 0 0 53029518.4 0.0 1.0X +OnHeapColumnVector 1 1 0 510959.6 0.0 0.0X +OffHeapColumnVector 894 895 2 458.2 2.2 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test read with LongType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 0 0 0 2657203.8 0.0 1.0X +OnHeapColumnVector 2469 2469 1 165.9 6.0 0.0X +OffHeapColumnVector 769 770 1 532.9 1.9 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test read with FloatType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 2243 2243 0 182.6 5.5 1.0X +OnHeapColumnVector 2504 2505 0 163.6 6.1 0.9X +OffHeapColumnVector 2891 2891 1 141.7 7.1 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test read with DoubleType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 2385 2386 2 171.8 5.8 1.0X +OnHeapColumnVector 2529 2531 2 162.0 6.2 0.9X +OffHeapColumnVector 3034 3037 5 135.0 7.4 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write and read with StringType, row length = 1: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 1946 1947 1 210.5 4.8 1.0X +OnHeapColumnVector 5184 5184 1 79.0 12.7 0.4X +OffHeapColumnVector 4703 4717 19 87.1 11.5 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write and read with StringType, row length = 5: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------- +ConstantColumnVector 1952 1954 3 209.9 4.8 1.0X +OnHeapColumnVector 5180 5183 4 79.1 12.6 0.4X +OffHeapColumnVector 4714 4717 3 86.9 11.5 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write and read with StringType, row length = 10: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 1947 1948 0 210.3 4.8 1.0X +OnHeapColumnVector 5161 5165 6 79.4 12.6 0.4X +OffHeapColumnVector 4692 4698 9 87.3 11.5 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write and read with StringType, row length = 15: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 1947 1947 0 210.3 4.8 1.0X +OnHeapColumnVector 5162 5167 7 79.3 12.6 0.4X +OffHeapColumnVector 4681 4685 6 87.5 11.4 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write and read with StringType, row length = 20: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 1945 1946 1 210.6 4.7 1.0X +OnHeapColumnVector 5155 5157 3 79.5 12.6 0.4X +OffHeapColumnVector 4675 4682 11 87.6 11.4 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write and read with StringType, row length = 30: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 1944 1947 5 210.7 4.7 1.0X +OnHeapColumnVector 5161 5162 1 79.4 12.6 0.4X +OffHeapColumnVector 4688 4692 5 87.4 11.4 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write and read with IntegerType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 893 894 1 458.8 2.2 1.0X +OnHeapColumnVector 894 895 1 458.0 2.2 1.0X +OffHeapColumnVector 893 893 0 458.6 2.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write and read with LongType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 2988 2992 5 137.1 7.3 1.0X +OnHeapColumnVector 3108 3110 3 131.8 7.6 1.0X +OffHeapColumnVector 3117 3119 3 131.4 7.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write and read with FloatType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 2877 2883 8 142.4 7.0 1.0X +OnHeapColumnVector 3139 3145 10 130.5 7.7 0.9X +OffHeapColumnVector 3011 3012 2 136.1 7.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test write and read with DoubleType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 3021 3024 4 135.6 7.4 1.0X +OnHeapColumnVector 3157 3165 12 129.8 7.7 1.0X +OffHeapColumnVector 3148 3153 7 130.1 7.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test isNull with StringType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 0 0 0 405143422.4 0.0 1.0X +OnHeapColumnVector 0 0 0 4428060.2 0.0 0.0X +OffHeapColumnVector 0 0 0 409190809.2 0.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test isNull with IntegerType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 0 0 0 405143422.4 0.0 1.0X +OnHeapColumnVector 0 0 0 4428060.2 0.0 0.0X +OffHeapColumnVector 0 0 0 409190809.2 0.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test isNull with LongType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 0 0 0 405143422.4 0.0 1.0X +OnHeapColumnVector 0 0 0 4428060.2 0.0 0.0X +OffHeapColumnVector 0 0 0 409190809.2 0.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test isNull with FloatType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 0 0 0 405143422.4 0.0 1.0X +OnHeapColumnVector 0 0 0 4428060.2 0.0 0.0X +OffHeapColumnVector 0 0 0 409190809.2 0.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Test isNull with DoubleType: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ConstantColumnVector 0 0 0 405143422.4 0.0 1.0X +OnHeapColumnVector 0 0 0 4428060.2 0.0 0.0X +OffHeapColumnVector 0 0 0 409190809.2 0.0 1.0X + diff --git a/sql/core/benchmarks/DataSourceReadBenchmark-jdk25-results.txt b/sql/core/benchmarks/DataSourceReadBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..fbe9b7826d547 --- /dev/null +++ b/sql/core/benchmarks/DataSourceReadBenchmark-jdk25-results.txt @@ -0,0 +1,438 @@ +================================================================================================ +SQL Single Numeric Column Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single BOOLEAN Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 10112 10350 337 1.6 642.9 1.0X +SQL Json 7346 7379 47 2.1 467.0 1.4X +SQL Json with UnsafeRow 8063 8098 50 2.0 512.6 1.3X +SQL Parquet Vectorized: DataPageV1 98 108 6 160.3 6.2 103.0X +SQL Parquet Vectorized: DataPageV2 104 116 12 151.1 6.6 97.2X +SQL Parquet MR: DataPageV1 1654 1666 17 9.5 105.2 6.1X +SQL Parquet MR: DataPageV2 1574 1583 13 10.0 100.1 6.4X +SQL ORC Vectorized 128 137 6 123.0 8.1 79.1X +SQL ORC MR 1444 1447 4 10.9 91.8 7.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Parquet Reader Single BOOLEAN Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +ParquetReader Vectorized: DataPageV1 80 81 2 197.6 5.1 1.0X +ParquetReader Vectorized: DataPageV2 92 93 1 171.6 5.8 0.9X +ParquetReader Vectorized -> Row: DataPageV1 80 82 1 196.0 5.1 1.0X +ParquetReader Vectorized -> Row: DataPageV2 92 94 1 170.1 5.9 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single TINYINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 9844 9870 37 1.6 625.9 1.0X +SQL Json 8096 8148 74 1.9 514.7 1.2X +SQL Json with UnsafeRow 8849 8852 5 1.8 562.6 1.1X +SQL Parquet Vectorized: DataPageV1 102 108 7 154.9 6.5 97.0X +SQL Parquet Vectorized: DataPageV2 99 110 7 159.2 6.3 99.6X +SQL Parquet MR: DataPageV1 1773 1774 3 8.9 112.7 5.6X +SQL Parquet MR: DataPageV2 1744 1756 16 9.0 110.9 5.6X +SQL ORC Vectorized 110 119 8 142.5 7.0 89.2X +SQL ORC MR 1449 1451 3 10.9 92.1 6.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Parquet Reader Single TINYINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +ParquetReader Vectorized: DataPageV1 47 49 2 336.1 3.0 1.0X +ParquetReader Vectorized: DataPageV2 47 49 2 336.3 3.0 1.0X +ParquetReader Vectorized -> Row: DataPageV1 46 48 1 338.7 3.0 1.0X +ParquetReader Vectorized -> Row: DataPageV2 46 47 1 338.5 3.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single SMALLINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 10558 10613 78 1.5 671.3 1.0X +SQL Json 8567 8578 16 1.8 544.7 1.2X +SQL Json with UnsafeRow 9313 9325 18 1.7 592.1 1.1X +SQL Parquet Vectorized: DataPageV1 130 135 3 120.8 8.3 81.1X +SQL Parquet Vectorized: DataPageV2 154 160 6 102.3 9.8 68.7X +SQL Parquet MR: DataPageV1 1898 1903 7 8.3 120.7 5.6X +SQL Parquet MR: DataPageV2 1867 1887 29 8.4 118.7 5.7X +SQL ORC Vectorized 147 158 7 106.9 9.4 71.8X +SQL ORC MR 1663 1677 21 9.5 105.7 6.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Parquet Reader Single SMALLINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +ParquetReader Vectorized: DataPageV1 150 153 3 104.6 9.6 1.0X +ParquetReader Vectorized: DataPageV2 181 183 1 86.8 11.5 0.8X +ParquetReader Vectorized -> Row: DataPageV1 155 162 8 101.2 9.9 1.0X +ParquetReader Vectorized -> Row: DataPageV2 185 191 5 84.8 11.8 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single INT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 11542 11608 93 1.4 733.8 1.0X +SQL Json 9182 9194 17 1.7 583.8 1.3X +SQL Json with UnsafeRow 10075 10098 32 1.6 640.6 1.1X +SQL Parquet Vectorized: DataPageV1 125 131 5 125.8 7.9 92.3X +SQL Parquet Vectorized: DataPageV2 200 212 9 78.5 12.7 57.6X +SQL Parquet MR: DataPageV1 1909 1958 70 8.2 121.4 6.0X +SQL Parquet MR: DataPageV2 1872 1880 11 8.4 119.0 6.2X +SQL ORC Vectorized 197 201 3 79.9 12.5 58.7X +SQL ORC MR 1753 1758 6 9.0 111.5 6.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Parquet Reader Single INT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +ParquetReader Vectorized: DataPageV1 159 163 4 98.7 10.1 1.0X +ParquetReader Vectorized: DataPageV2 248 252 6 63.5 15.7 0.6X +ParquetReader Vectorized -> Row: DataPageV1 168 174 8 93.4 10.7 0.9X +ParquetReader Vectorized -> Row: DataPageV2 250 253 3 63.0 15.9 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single BIGINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 11580 11646 93 1.4 736.3 1.0X +SQL Json 9224 9252 40 1.7 586.5 1.3X +SQL Json with UnsafeRow 9933 9946 18 1.6 631.5 1.2X +SQL Parquet Vectorized: DataPageV1 273 295 10 57.6 17.4 42.4X +SQL Parquet Vectorized: DataPageV2 253 259 3 62.1 16.1 45.7X +SQL Parquet MR: DataPageV1 2284 2311 38 6.9 145.2 5.1X +SQL Parquet MR: DataPageV2 1857 1885 39 8.5 118.1 6.2X +SQL ORC Vectorized 189 201 9 83.1 12.0 61.2X +SQL ORC MR 1810 1811 2 8.7 115.1 6.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Parquet Reader Single BIGINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +ParquetReader Vectorized: DataPageV1 337 345 6 46.6 21.5 1.0X +ParquetReader Vectorized: DataPageV2 294 303 10 53.4 18.7 1.1X +ParquetReader Vectorized -> Row: DataPageV1 355 358 3 44.3 22.6 1.0X +ParquetReader Vectorized -> Row: DataPageV2 298 302 7 52.8 18.9 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single FLOAT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 11106 11116 13 1.4 706.1 1.0X +SQL Json 10993 11011 25 1.4 698.9 1.0X +SQL Json with UnsafeRow 11750 11775 36 1.3 747.0 0.9X +SQL Parquet Vectorized: DataPageV1 100 107 5 157.3 6.4 111.1X +SQL Parquet Vectorized: DataPageV2 106 111 4 149.1 6.7 105.2X +SQL Parquet MR: DataPageV1 1985 1998 18 7.9 126.2 5.6X +SQL Parquet MR: DataPageV2 1906 1923 23 8.3 121.2 5.8X +SQL ORC Vectorized 246 258 12 63.9 15.7 45.1X +SQL ORC MR 1744 1781 53 9.0 110.9 6.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Parquet Reader Single FLOAT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +ParquetReader Vectorized: DataPageV1 148 155 6 105.9 9.4 1.0X +ParquetReader Vectorized: DataPageV2 150 152 3 105.2 9.5 1.0X +ParquetReader Vectorized -> Row: DataPageV1 152 158 6 103.5 9.7 1.0X +ParquetReader Vectorized -> Row: DataPageV2 156 162 10 100.6 9.9 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single DOUBLE Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 11628 11642 19 1.4 739.3 1.0X +SQL Json 11422 11434 16 1.4 726.2 1.0X +SQL Json with UnsafeRow 12276 12335 84 1.3 780.5 0.9X +SQL Parquet Vectorized: DataPageV1 288 296 13 54.5 18.3 40.3X +SQL Parquet Vectorized: DataPageV2 283 286 2 55.5 18.0 41.0X +SQL Parquet MR: DataPageV1 2337 2349 17 6.7 148.6 5.0X +SQL Parquet MR: DataPageV2 2282 2287 7 6.9 145.1 5.1X +SQL ORC Vectorized 526 538 15 29.9 33.4 22.1X +SQL ORC MR 2101 2110 12 7.5 133.6 5.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Parquet Reader Single DOUBLE Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +ParquetReader Vectorized: DataPageV1 353 361 6 44.6 22.4 1.0X +ParquetReader Vectorized: DataPageV2 350 356 12 44.9 22.3 1.0X +ParquetReader Vectorized -> Row: DataPageV1 351 361 7 44.9 22.3 1.0X +ParquetReader Vectorized -> Row: DataPageV2 361 367 6 43.6 22.9 1.0X + + +================================================================================================ +SQL Single Numeric Column Scan in Struct +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single TINYINT Column Scan in Struct: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------- +SQL ORC MR 2076 2085 12 7.6 132.0 1.0X +SQL ORC Vectorized (Nested Column Disabled) 2062 2077 21 7.6 131.1 1.0X +SQL ORC Vectorized (Nested Column Enabled) 148 159 17 106.0 9.4 14.0X +SQL Parquet MR: DataPageV1 2326 2363 53 6.8 147.9 0.9X +SQL Parquet Vectorized: DataPageV1 (Nested Column Disabled) 2712 2747 50 5.8 172.4 0.8X +SQL Parquet Vectorized: DataPageV1 (Nested Column Enabled) 114 129 30 137.8 7.3 18.2X +SQL Parquet MR: DataPageV2 2278 2285 10 6.9 144.8 0.9X +SQL Parquet Vectorized: DataPageV2 (Nested Column Disabled) 2623 2665 59 6.0 166.8 0.8X +SQL Parquet Vectorized: DataPageV2 (Nested Column Enabled) 113 119 6 139.6 7.2 18.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single SMALLINT Column Scan in Struct: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------- +SQL ORC MR 2217 2220 5 7.1 141.0 1.0X +SQL ORC Vectorized (Nested Column Disabled) 2212 2221 12 7.1 140.6 1.0X +SQL ORC Vectorized (Nested Column Enabled) 167 171 5 94.4 10.6 13.3X +SQL Parquet MR: DataPageV1 2441 2472 45 6.4 155.2 0.9X +SQL Parquet Vectorized: DataPageV1 (Nested Column Disabled) 2775 2837 88 5.7 176.5 0.8X +SQL Parquet Vectorized: DataPageV1 (Nested Column Enabled) 124 132 6 126.5 7.9 17.8X +SQL Parquet MR: DataPageV2 2361 2362 2 6.7 150.1 0.9X +SQL Parquet Vectorized: DataPageV2 (Nested Column Disabled) 2658 2694 52 5.9 169.0 0.8X +SQL Parquet Vectorized: DataPageV2 (Nested Column Enabled) 153 164 9 103.0 9.7 14.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single INT Column Scan in Struct: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------- +SQL ORC MR 2240 2267 37 7.0 142.4 1.0X +SQL ORC Vectorized (Nested Column Disabled) 2208 2236 39 7.1 140.4 1.0X +SQL ORC Vectorized (Nested Column Enabled) 168 180 7 93.6 10.7 13.3X +SQL Parquet MR: DataPageV1 2471 2513 59 6.4 157.1 0.9X +SQL Parquet Vectorized: DataPageV1 (Nested Column Disabled) 3050 3064 20 5.2 193.9 0.7X +SQL Parquet Vectorized: DataPageV1 (Nested Column Enabled) 126 131 6 124.5 8.0 17.7X +SQL Parquet MR: DataPageV2 2380 2382 3 6.6 151.3 0.9X +SQL Parquet Vectorized: DataPageV2 (Nested Column Disabled) 2947 2953 9 5.3 187.4 0.8X +SQL Parquet Vectorized: DataPageV2 (Nested Column Enabled) 242 261 14 64.9 15.4 9.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single BIGINT Column Scan in Struct: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------- +SQL ORC MR 2275 2294 26 6.9 144.6 1.0X +SQL ORC Vectorized (Nested Column Disabled) 2260 2263 5 7.0 143.7 1.0X +SQL ORC Vectorized (Nested Column Enabled) 162 180 23 97.1 10.3 14.0X +SQL Parquet MR: DataPageV1 2767 2770 4 5.7 175.9 0.8X +SQL Parquet Vectorized: DataPageV1 (Nested Column Disabled) 3267 3294 38 4.8 207.7 0.7X +SQL Parquet Vectorized: DataPageV1 (Nested Column Enabled) 293 314 12 53.7 18.6 7.8X +SQL Parquet MR: DataPageV2 2304 2326 32 6.8 146.5 1.0X +SQL Parquet Vectorized: DataPageV2 (Nested Column Disabled) 2803 2825 30 5.6 178.2 0.8X +SQL Parquet Vectorized: DataPageV2 (Nested Column Enabled) 266 275 7 59.1 16.9 8.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single FLOAT Column Scan in Struct: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------- +SQL ORC MR 2364 2372 12 6.7 150.3 1.0X +SQL ORC Vectorized (Nested Column Disabled) 2302 2323 30 6.8 146.4 1.0X +SQL ORC Vectorized (Nested Column Enabled) 262 266 3 60.1 16.6 9.0X +SQL Parquet MR: DataPageV1 2437 2446 12 6.5 154.9 1.0X +SQL Parquet Vectorized: DataPageV1 (Nested Column Disabled) 2997 3012 21 5.2 190.5 0.8X +SQL Parquet Vectorized: DataPageV1 (Nested Column Enabled) 108 115 6 145.3 6.9 21.8X +SQL Parquet MR: DataPageV2 2301 2310 12 6.8 146.3 1.0X +SQL Parquet Vectorized: DataPageV2 (Nested Column Disabled) 2922 2924 4 5.4 185.7 0.8X +SQL Parquet Vectorized: DataPageV2 (Nested Column Enabled) 114 123 7 137.7 7.3 20.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Single DOUBLE Column Scan in Struct: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------- +SQL ORC MR 2578 2586 12 6.1 163.9 1.0X +SQL ORC Vectorized (Nested Column Disabled) 2508 2520 16 6.3 159.5 1.0X +SQL ORC Vectorized (Nested Column Enabled) 525 528 4 29.9 33.4 4.9X +SQL Parquet MR: DataPageV1 2725 2725 1 5.8 173.2 0.9X +SQL Parquet Vectorized: DataPageV1 (Nested Column Disabled) 3237 3247 14 4.9 205.8 0.8X +SQL Parquet Vectorized: DataPageV1 (Nested Column Enabled) 306 313 10 51.4 19.5 8.4X +SQL Parquet MR: DataPageV2 2661 2665 6 5.9 169.2 1.0X +SQL Parquet Vectorized: DataPageV2 (Nested Column Disabled) 3164 3176 18 5.0 201.1 0.8X +SQL Parquet Vectorized: DataPageV2 (Nested Column Enabled) 287 304 12 54.8 18.2 9.0X + + +================================================================================================ +SQL Nested Column Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +SQL Nested Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------- +SQL ORC MR 15776 16040 274 0.1 15045.4 1.0X +SQL ORC Vectorized (Nested Column Disabled) 15887 15970 68 0.1 15151.1 1.0X +SQL ORC Vectorized (Nested Column Enabled) 7524 7572 32 0.1 7175.6 2.1X +SQL Parquet MR: DataPageV1 10498 10658 87 0.1 10011.4 1.5X +SQL Parquet Vectorized: DataPageV1 (Nested Column Disabled) 10884 11081 121 0.1 10379.5 1.4X +SQL Parquet Vectorized: DataPageV1 (Nested Column Enabled) 8056 8192 102 0.1 7683.0 2.0X +SQL Parquet MR: DataPageV2 11173 11239 51 0.1 10655.3 1.4X +SQL Parquet Vectorized: DataPageV2 (Nested Column Disabled) 11605 11700 57 0.1 11067.1 1.4X +SQL Parquet Vectorized: DataPageV2 (Nested Column Enabled) 6282 6427 81 0.2 5990.9 2.5X + + +================================================================================================ +Int and String Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Int and String Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 10866 10889 33 1.0 1036.3 1.0X +SQL Json 10470 10502 46 1.0 998.5 1.0X +SQL Parquet Vectorized: DataPageV1 1604 1616 17 6.5 152.9 6.8X +SQL Parquet Vectorized: DataPageV2 1859 1869 14 5.6 177.3 5.8X +SQL Parquet MR: DataPageV1 3807 3828 31 2.8 363.0 2.9X +SQL Parquet MR: DataPageV2 3660 3669 13 2.9 349.0 3.0X +SQL ORC Vectorized 1604 1612 10 6.5 153.0 6.8X +SQL ORC MR 3476 3477 3 3.0 331.5 3.1X + + +================================================================================================ +Repeated String Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Repeated String: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 5426 5459 47 1.9 517.4 1.0X +SQL Json 6263 6307 63 1.7 597.3 0.9X +SQL Parquet Vectorized: DataPageV1 442 447 5 23.7 42.1 12.3X +SQL Parquet Vectorized: DataPageV2 428 434 4 24.5 40.8 12.7X +SQL Parquet MR: DataPageV1 1701 1716 22 6.2 162.2 3.2X +SQL Parquet MR: DataPageV2 1650 1667 24 6.4 157.4 3.3X +SQL ORC Vectorized 334 340 8 31.3 31.9 16.2X +SQL ORC MR 1678 1686 12 6.2 160.0 3.2X + + +================================================================================================ +Partitioned Table Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Partitioned Table: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------- +Data column - CSV 10890 10890 0 1.4 692.4 1.0X +Data column - Json 9322 9439 166 1.7 592.7 1.2X +Data column - Parquet Vectorized: DataPageV1 120 125 6 130.9 7.6 90.6X +Data column - Parquet Vectorized: DataPageV2 256 262 5 61.3 16.3 42.5X +Data column - Parquet MR: DataPageV1 2213 2222 13 7.1 140.7 4.9X +Data column - Parquet MR: DataPageV2 2174 2184 15 7.2 138.2 5.0X +Data column - ORC Vectorized 157 170 9 100.2 10.0 69.4X +Data column - ORC MR 2027 2028 2 7.8 128.9 5.4X +Partition column - CSV 3898 3911 19 4.0 247.8 2.8X +Partition column - Json 8249 8256 9 1.9 524.5 1.3X +Partition column - Parquet Vectorized: DataPageV1 36 41 6 436.0 2.3 301.9X +Partition column - Parquet Vectorized: DataPageV2 35 41 6 450.9 2.2 312.2X +Partition column - Parquet MR: DataPageV1 1136 1153 24 13.8 72.2 9.6X +Partition column - Parquet MR: DataPageV2 1154 1164 15 13.6 73.3 9.4X +Partition column - ORC Vectorized 35 39 6 455.0 2.2 315.1X +Partition column - ORC MR 1127 1129 2 14.0 71.7 9.7X +Both columns - CSV 10831 10835 6 1.5 688.6 1.0X +Both columns - Json 9398 9427 41 1.7 597.5 1.2X +Both columns - Parquet Vectorized: DataPageV1 134 140 6 117.7 8.5 81.5X +Both columns - Parquet Vectorized: DataPageV2 277 281 3 56.8 17.6 39.3X +Both columns - Parquet MR: DataPageV1 2337 2343 9 6.7 148.6 4.7X +Both columns - Parquet MR: DataPageV2 2255 2271 22 7.0 143.4 4.8X +Both columns - ORC Vectorized 189 207 10 83.0 12.0 57.5X +Both columns - ORC MR 2091 2114 34 7.5 132.9 5.2X + + +================================================================================================ +String with Nulls Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +String with Nulls Scan (0.0%): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 7098 7105 10 1.5 676.9 1.0X +SQL Json 8968 8972 5 1.2 855.3 0.8X +SQL Parquet Vectorized: DataPageV1 1034 1035 1 10.1 98.6 6.9X +SQL Parquet Vectorized: DataPageV2 1287 1289 2 8.1 122.8 5.5X +SQL Parquet MR: DataPageV1 3530 3532 3 3.0 336.6 2.0X +SQL Parquet MR: DataPageV2 3234 3241 10 3.2 308.4 2.2X +ParquetReader Vectorized: DataPageV1 746 750 4 14.1 71.2 9.5X +ParquetReader Vectorized: DataPageV2 1085 1087 3 9.7 103.4 6.5X +SQL ORC Vectorized 709 734 35 14.8 67.6 10.0X +SQL ORC MR 2804 2805 1 3.7 267.4 2.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +String with Nulls Scan (50.0%): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 5504 5577 102 1.9 524.9 1.0X +SQL Json 7572 7617 64 1.4 722.2 0.7X +SQL Parquet Vectorized: DataPageV1 775 793 22 13.5 73.9 7.1X +SQL Parquet Vectorized: DataPageV2 913 929 26 11.5 87.1 6.0X +SQL Parquet MR: DataPageV1 2649 2687 54 4.0 252.6 2.1X +SQL Parquet MR: DataPageV2 2662 2664 3 3.9 253.9 2.1X +ParquetReader Vectorized: DataPageV1 788 796 7 13.3 75.2 7.0X +ParquetReader Vectorized: DataPageV2 897 903 5 11.7 85.6 6.1X +SQL ORC Vectorized 930 967 58 11.3 88.7 5.9X +SQL ORC MR 2676 2715 54 3.9 255.2 2.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +String with Nulls Scan (95.0%): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 3763 3776 19 2.8 358.8 1.0X +SQL Json 5158 5181 33 2.0 491.9 0.7X +SQL Parquet Vectorized: DataPageV1 180 205 20 58.3 17.2 20.9X +SQL Parquet Vectorized: DataPageV2 202 214 12 51.8 19.3 18.6X +SQL Parquet MR: DataPageV1 1696 1710 20 6.2 161.8 2.2X +SQL Parquet MR: DataPageV2 1612 1629 24 6.5 153.7 2.3X +ParquetReader Vectorized: DataPageV1 169 171 3 61.9 16.1 22.2X +ParquetReader Vectorized: DataPageV2 191 197 12 55.0 18.2 19.7X +SQL ORC Vectorized 279 282 5 37.6 26.6 13.5X +SQL ORC MR 1601 1608 10 6.5 152.7 2.4X + + +================================================================================================ +Single Column Scan From Wide Columns +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Single Column Scan from 10 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 1466 1467 1 0.7 1398.0 1.0X +SQL Json 1563 1564 2 0.7 1490.3 0.9X +SQL Parquet Vectorized: DataPageV1 28 31 5 38.0 26.3 53.1X +SQL Parquet Vectorized: DataPageV2 36 40 5 29.0 34.5 40.5X +SQL Parquet MR: DataPageV1 156 168 4 6.7 149.2 9.4X +SQL Parquet MR: DataPageV2 167 172 5 6.3 159.0 8.8X +SQL ORC Vectorized 30 35 5 34.4 29.1 48.1X +SQL ORC MR 130 136 4 8.1 123.8 11.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Single Column Scan from 50 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 2753 2758 7 0.4 2625.4 1.0X +SQL Json 5031 5102 100 0.2 4798.3 0.5X +SQL Parquet Vectorized: DataPageV1 31 37 5 34.1 29.3 89.5X +SQL Parquet Vectorized: DataPageV2 39 43 5 26.6 37.6 69.9X +SQL Parquet MR: DataPageV1 163 172 7 6.4 155.6 16.9X +SQL Parquet MR: DataPageV2 163 171 7 6.4 155.6 16.9X +SQL ORC Vectorized 34 39 5 30.6 32.7 80.3X +SQL ORC MR 136 144 7 7.7 129.7 20.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Single Column Scan from 100 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +SQL CSV 4438 4454 22 0.2 4232.8 1.0X +SQL Json 9568 9630 87 0.1 9125.2 0.5X +SQL Parquet Vectorized: DataPageV1 36 51 11 28.9 34.6 122.2X +SQL Parquet Vectorized: DataPageV2 44 51 6 23.6 42.4 99.8X +SQL Parquet MR: DataPageV1 173 187 5 6.1 164.9 25.7X +SQL Parquet MR: DataPageV2 178 184 4 5.9 170.2 24.9X +SQL ORC Vectorized 39 42 4 26.9 37.2 113.9X +SQL ORC MR 146 157 7 7.2 139.1 30.4X + + diff --git a/sql/core/benchmarks/DatasetBenchmark-jdk25-results.txt b/sql/core/benchmarks/DatasetBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..4ca5a1af4786a --- /dev/null +++ b/sql/core/benchmarks/DatasetBenchmark-jdk25-results.txt @@ -0,0 +1,46 @@ +================================================================================================ +Dataset Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +back-to-back map long: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +RDD 6666 6681 21 15.0 66.7 1.0X +DataFrame 1191 1248 81 84.0 11.9 5.6X +Dataset 1894 1934 57 52.8 18.9 3.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +back-to-back map: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +RDD 7499 7585 121 13.3 75.0 1.0X +DataFrame 2457 2470 18 40.7 24.6 3.1X +Dataset 7231 7239 11 13.8 72.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +back-to-back filter Long: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +RDD 4371 4412 58 22.9 43.7 1.0X +DataFrame 819 872 70 122.1 8.2 5.3X +Dataset 1633 1639 8 61.2 16.3 2.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +back-to-back filter: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +RDD 1990 2035 64 50.3 19.9 1.0X +DataFrame 117 130 12 855.6 1.2 17.0X +Dataset 2133 2151 26 46.9 21.3 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +aggregate: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +RDD sum 1228 1235 10 81.4 12.3 1.0X +DataFrame sum 73 88 12 1362.2 0.7 16.7X +Dataset sum using Aggregator 1569 1574 8 63.7 15.7 0.8X +Dataset complex Aggregator 4644 4679 49 21.5 46.4 0.3X + + diff --git a/sql/core/benchmarks/DateTimeBenchmark-jdk25-results.txt b/sql/core/benchmarks/DateTimeBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..18ac977366fb0 --- /dev/null +++ b/sql/core/benchmarks/DateTimeBenchmark-jdk25-results.txt @@ -0,0 +1,461 @@ +================================================================================================ +datetime +/- interval +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +datetime +/- interval: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date + interval(m) 827 865 58 12.1 82.7 1.0X +date + interval(m, d) 808 823 21 12.4 80.8 1.0X +date + interval(m, d, ms) 3344 3345 1 3.0 334.4 0.2X +date - interval(m) 793 795 2 12.6 79.3 1.0X +date - interval(m, d) 806 815 8 12.4 80.6 1.0X +date - interval(m, d, ms) 3384 3385 2 3.0 338.4 0.2X +timestamp + interval(m) 1652 1657 7 6.1 165.2 0.5X +timestamp + interval(m, d) 1701 1704 4 5.9 170.1 0.5X +timestamp + interval(m, d, ms) 2033 2033 0 4.9 203.3 0.4X +timestamp - interval(m) 1778 1782 6 5.6 177.8 0.5X +timestamp - interval(m, d) 1839 1842 4 5.4 183.9 0.4X +timestamp - interval(m, d, ms) 2045 2050 8 4.9 204.5 0.4X + + +================================================================================================ +Extract components +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +cast to timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +cast to timestamp wholestage off 197 199 2 50.7 19.7 1.0X +cast to timestamp wholestage on 206 214 6 48.6 20.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +year of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +year of timestamp wholestage off 656 665 12 15.2 65.6 1.0X +year of timestamp wholestage on 604 613 14 16.6 60.4 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +quarter of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +quarter of timestamp wholestage off 648 649 1 15.4 64.8 1.0X +quarter of timestamp wholestage on 622 630 5 16.1 62.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +month of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +month of timestamp wholestage off 623 626 4 16.0 62.3 1.0X +month of timestamp wholestage on 620 624 3 16.1 62.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +weekofyear of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +weekofyear of timestamp wholestage off 1002 1003 2 10.0 100.2 1.0X +weekofyear of timestamp wholestage on 981 992 19 10.2 98.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +day of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +day of timestamp wholestage off 628 628 1 15.9 62.8 1.0X +day of timestamp wholestage on 621 626 4 16.1 62.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dayofyear of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +dayofyear of timestamp wholestage off 667 679 17 15.0 66.7 1.0X +dayofyear of timestamp wholestage on 659 669 9 15.2 65.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dayofmonth of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +dayofmonth of timestamp wholestage off 630 644 21 15.9 63.0 1.0X +dayofmonth of timestamp wholestage on 621 626 3 16.1 62.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dayofweek of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +dayofweek of timestamp wholestage off 792 794 2 12.6 79.2 1.0X +dayofweek of timestamp wholestage on 786 787 2 12.7 78.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +weekday of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +weekday of timestamp wholestage off 730 745 23 13.7 73.0 1.0X +weekday of timestamp wholestage on 730 734 3 13.7 73.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +hour of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +hour of timestamp wholestage off 539 540 1 18.6 53.9 1.0X +hour of timestamp wholestage on 535 538 4 18.7 53.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +minute of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +minute of timestamp wholestage off 537 540 5 18.6 53.7 1.0X +minute of timestamp wholestage on 538 544 13 18.6 53.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +second of timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +second of timestamp wholestage off 535 535 0 18.7 53.5 1.0X +second of timestamp wholestage on 546 550 2 18.3 54.6 1.0X + + +================================================================================================ +Current date and time +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +current_date: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +current_date wholestage off 189 191 2 52.8 18.9 1.0X +current_date wholestage on 203 206 3 49.4 20.3 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +current_timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +current_timestamp wholestage off 211 239 40 47.4 21.1 1.0X +current_timestamp wholestage on 210 220 11 47.5 21.0 1.0X + + +================================================================================================ +Date arithmetic +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +cast to date: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +cast to date wholestage off 571 574 5 17.5 57.1 1.0X +cast to date wholestage on 574 577 4 17.4 57.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +last_day: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +last_day wholestage off 659 661 3 15.2 65.9 1.0X +last_day wholestage on 659 668 6 15.2 65.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +next_day: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +next_day wholestage off 607 609 3 16.5 60.7 1.0X +next_day wholestage on 610 616 4 16.4 61.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_add: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_add wholestage off 559 562 4 17.9 55.9 1.0X +date_add wholestage on 572 579 9 17.5 57.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_sub: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_sub wholestage off 566 577 15 17.7 56.6 1.0X +date_sub wholestage on 573 575 2 17.5 57.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +add_months: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +add_months wholestage off 791 793 3 12.6 79.1 1.0X +add_months wholestage on 792 799 5 12.6 79.2 1.0X + + +================================================================================================ +Formatting dates +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +format date: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +format date wholestage off 2790 2842 74 3.6 279.0 1.0X +format date wholestage on 2810 2831 13 3.6 281.0 1.0X + + +================================================================================================ +Formatting timestamps +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +from_unixtime: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +from_unixtime wholestage off 2669 2671 4 3.7 266.9 1.0X +from_unixtime wholestage on 2648 2657 9 3.8 264.8 1.0X + + +================================================================================================ +Convert timestamps +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +from_utc_timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +from_utc_timestamp wholestage off 681 686 7 14.7 68.1 1.0X +from_utc_timestamp wholestage on 719 725 7 13.9 71.9 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +to_utc_timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +to_utc_timestamp wholestage off 824 826 2 12.1 82.4 1.0X +to_utc_timestamp wholestage on 856 860 3 11.7 85.6 1.0X + + +================================================================================================ +Intervals +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +cast interval: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +cast interval wholestage off 245 248 5 40.9 24.5 1.0X +cast interval wholestage on 210 215 5 47.7 21.0 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +datediff: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +datediff wholestage off 963 965 2 10.4 96.3 1.0X +datediff wholestage on 911 917 6 11.0 91.1 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +months_between: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +months_between wholestage off 3058 3059 2 3.3 305.8 1.0X +months_between wholestage on 3073 3082 5 3.3 307.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +window: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +window wholestage off 351 352 1 2.8 351.3 1.0X +window wholestage on 703 710 7 1.4 703.4 0.5X + + +================================================================================================ +Truncation +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc YEAR: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc YEAR wholestage off 1631 1633 3 6.1 163.1 1.0X +date_trunc YEAR wholestage on 1671 1679 5 6.0 167.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc YYYY: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc YYYY wholestage off 1635 1643 11 6.1 163.5 1.0X +date_trunc YYYY wholestage on 1679 1682 2 6.0 167.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc YY: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc YY wholestage off 1631 1635 5 6.1 163.1 1.0X +date_trunc YY wholestage on 1681 1683 1 5.9 168.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc MON: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc MON wholestage off 1656 1657 2 6.0 165.6 1.0X +date_trunc MON wholestage on 1626 1630 3 6.2 162.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc MONTH: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc MONTH wholestage off 1655 1655 1 6.0 165.5 1.0X +date_trunc MONTH wholestage on 1625 1629 4 6.2 162.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc MM: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc MM wholestage off 1655 1658 4 6.0 165.5 1.0X +date_trunc MM wholestage on 1624 1633 11 6.2 162.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc DAY: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc DAY wholestage off 1194 1195 2 8.4 119.4 1.0X +date_trunc DAY wholestage on 1260 1264 5 7.9 126.0 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc DD: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc DD wholestage off 1195 1197 4 8.4 119.5 1.0X +date_trunc DD wholestage on 1260 1262 1 7.9 126.0 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc HOUR: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc HOUR wholestage off 1197 1199 4 8.4 119.7 1.0X +date_trunc HOUR wholestage on 1149 1152 2 8.7 114.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc MINUTE: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc MINUTE wholestage off 1290 1290 0 7.8 129.0 1.0X +date_trunc MINUTE wholestage on 1216 1217 1 8.2 121.6 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc SECOND: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc SECOND wholestage off 309 309 1 32.4 30.9 1.0X +date_trunc SECOND wholestage on 274 277 2 36.5 27.4 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc WEEK: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc WEEK wholestage off 1523 1543 27 6.6 152.3 1.0X +date_trunc WEEK wholestage on 1644 1645 2 6.1 164.4 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +date_trunc QUARTER: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +date_trunc QUARTER wholestage off 2130 2141 15 4.7 213.0 1.0X +date_trunc QUARTER wholestage on 1996 2008 24 5.0 199.6 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +trunc year: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +trunc year wholestage off 767 767 1 13.0 76.7 1.0X +trunc year wholestage on 728 732 4 13.7 72.8 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +trunc yyyy: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +trunc yyyy wholestage off 766 766 0 13.1 76.6 1.0X +trunc yyyy wholestage on 727 731 3 13.7 72.7 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +trunc yy: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +trunc yy wholestage off 766 767 0 13.0 76.6 1.0X +trunc yy wholestage on 726 730 3 13.8 72.6 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +trunc mon: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +trunc mon wholestage off 727 728 1 13.8 72.7 1.0X +trunc mon wholestage on 696 703 7 14.4 69.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +trunc month: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +trunc month wholestage off 721 724 4 13.9 72.1 1.0X +trunc month wholestage on 693 705 11 14.4 69.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +trunc mm: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +trunc mm wholestage off 728 728 0 13.7 72.8 1.0X +trunc mm wholestage on 700 706 6 14.3 70.0 1.0X + + +================================================================================================ +Parsing +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +to timestamp str: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +to timestamp str wholestage off 89 91 2 11.2 89.5 1.0X +to timestamp str wholestage on 86 97 14 11.6 86.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +to_timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +to_timestamp wholestage off 548 548 0 1.8 548.4 1.0X +to_timestamp wholestage on 571 575 4 1.8 571.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +to_unix_timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +to_unix_timestamp wholestage off 574 574 0 1.7 573.8 1.0X +to_unix_timestamp wholestage on 569 576 10 1.8 569.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +to date str: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +to date str wholestage off 106 108 4 9.4 105.9 1.0X +to date str wholestage on 105 106 1 9.5 105.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +to_date: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +to_date wholestage off 543 545 2 1.8 543.5 1.0X +to_date wholestage on 555 556 1 1.8 554.9 1.0X + + +================================================================================================ +Conversion from/to external types +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +To/from Java's date-time: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +From java.sql.Date 292 293 2 17.1 58.4 1.0X +From java.time.LocalDate 227 229 3 22.0 45.4 1.3X +Collect java.sql.Date 1382 1410 28 3.6 276.4 0.2X +Collect java.time.LocalDate 1033 1171 123 4.8 206.7 0.3X +From java.sql.Timestamp 229 246 16 21.9 45.7 1.3X +From java.time.Instant 201 217 14 24.9 40.1 1.5X +Collect longs 1030 1170 133 4.9 206.0 0.3X +Collect java.sql.Timestamp 946 1219 238 5.3 189.2 0.3X +Collect java.time.Instant 1036 1113 107 4.8 207.2 0.3X +java.sql.Date to Hive string 3823 3971 129 1.3 764.6 0.1X +java.time.LocalDate to Hive string 3058 3188 190 1.6 611.7 0.1X +java.sql.Timestamp to Hive string 6532 6816 249 0.8 1306.3 0.0X +java.time.Instant to Hive string 4228 4275 51 1.2 845.6 0.1X + + diff --git a/sql/core/benchmarks/DateTimeRebaseBenchmark-jdk25-results.txt b/sql/core/benchmarks/DateTimeRebaseBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..39faa89344fb7 --- /dev/null +++ b/sql/core/benchmarks/DateTimeRebaseBenchmark-jdk25-results.txt @@ -0,0 +1,154 @@ +================================================================================================ +Rebasing dates/timestamps in Parquet datasource +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Save DATE to parquet: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1582, noop 9760 9760 0 10.2 97.6 1.0X +before 1582, noop 5631 5631 0 17.8 56.3 1.7X +after 1582, rebase EXCEPTION 19739 19739 0 5.1 197.4 0.5X +after 1582, rebase LEGACY 20078 20078 0 5.0 200.8 0.5X +after 1582, rebase CORRECTED 19812 19812 0 5.0 198.1 0.5X +before 1582, rebase LEGACY 15442 15442 0 6.5 154.4 0.6X +before 1582, rebase CORRECTED 15364 15364 0 6.5 153.6 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Load DATE from parquet: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1582, vec off, rebase EXCEPTION 11110 11145 36 9.0 111.1 1.0X +after 1582, vec off, rebase LEGACY 11153 11193 35 9.0 111.5 1.0X +after 1582, vec off, rebase CORRECTED 11238 11279 36 8.9 112.4 1.0X +after 1582, vec on, rebase EXCEPTION 2768 2825 51 36.1 27.7 4.0X +after 1582, vec on, rebase LEGACY 2794 2826 28 35.8 27.9 4.0X +after 1582, vec on, rebase CORRECTED 2790 2827 34 35.8 27.9 4.0X +before 1582, vec off, rebase LEGACY 11330 11427 86 8.8 113.3 1.0X +before 1582, vec off, rebase CORRECTED 11143 11197 91 9.0 111.4 1.0X +before 1582, vec on, rebase LEGACY 3200 3235 31 31.2 32.0 3.5X +before 1582, vec on, rebase CORRECTED 2716 2721 7 36.8 27.2 4.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Save TIMESTAMP_INT96 to parquet: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1900, noop 2418 2418 0 41.4 24.2 1.0X +before 1900, noop 2420 2420 0 41.3 24.2 1.0X +after 1900, rebase EXCEPTION 12207 12207 0 8.2 122.1 0.2X +after 1900, rebase LEGACY 12076 12076 0 8.3 120.8 0.2X +after 1900, rebase CORRECTED 12596 12596 0 7.9 126.0 0.2X +before 1900, rebase LEGACY 14593 14593 0 6.9 145.9 0.2X +before 1900, rebase CORRECTED 12756 12756 0 7.8 127.6 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Load TIMESTAMP_INT96 from parquet: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1900, vec off, rebase EXCEPTION 14916 14965 52 6.7 149.2 1.0X +after 1900, vec off, rebase LEGACY 15575 15605 32 6.4 155.8 1.0X +after 1900, vec off, rebase CORRECTED 14878 14917 58 6.7 148.8 1.0X +after 1900, vec on, rebase EXCEPTION 4333 4368 37 23.1 43.3 3.4X +after 1900, vec on, rebase LEGACY 4389 4405 18 22.8 43.9 3.4X +after 1900, vec on, rebase CORRECTED 4364 4371 8 22.9 43.6 3.4X +before 1900, vec off, rebase LEGACY 17118 17212 94 5.8 171.2 0.9X +before 1900, vec off, rebase CORRECTED 14904 14953 62 6.7 149.0 1.0X +before 1900, vec on, rebase LEGACY 6293 6309 25 15.9 62.9 2.4X +before 1900, vec on, rebase CORRECTED 4384 4398 19 22.8 43.8 3.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Save TIMESTAMP_MICROS to parquet: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1900, noop 2401 2401 0 41.7 24.0 1.0X +before 1900, noop 2374 2374 0 42.1 23.7 1.0X +after 1900, rebase EXCEPTION 11414 11414 0 8.8 114.1 0.2X +after 1900, rebase LEGACY 11313 11313 0 8.8 113.1 0.2X +after 1900, rebase CORRECTED 11255 11255 0 8.9 112.5 0.2X +before 1900, rebase LEGACY 13252 13252 0 7.5 132.5 0.2X +before 1900, rebase CORRECTED 11245 11245 0 8.9 112.4 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Load TIMESTAMP_MICROS from parquet: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1900, vec off, rebase EXCEPTION 14316 14337 22 7.0 143.2 1.0X +after 1900, vec off, rebase LEGACY 14520 14531 9 6.9 145.2 1.0X +after 1900, vec off, rebase CORRECTED 14271 14351 74 7.0 142.7 1.0X +after 1900, vec on, rebase EXCEPTION 4104 4139 50 24.4 41.0 3.5X +after 1900, vec on, rebase LEGACY 4203 4220 27 23.8 42.0 3.4X +after 1900, vec on, rebase CORRECTED 4168 4219 45 24.0 41.7 3.4X +before 1900, vec off, rebase LEGACY 16434 16480 45 6.1 164.3 0.9X +before 1900, vec off, rebase CORRECTED 14376 14445 71 7.0 143.8 1.0X +before 1900, vec on, rebase LEGACY 5925 5933 9 16.9 59.3 2.4X +before 1900, vec on, rebase CORRECTED 4106 4130 33 24.4 41.1 3.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Save TIMESTAMP_MILLIS to parquet: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1900, noop 2503 2503 0 40.0 25.0 1.0X +before 1900, noop 2453 2453 0 40.8 24.5 1.0X +after 1900, rebase EXCEPTION 11961 11961 0 8.4 119.6 0.2X +after 1900, rebase LEGACY 11810 11810 0 8.5 118.1 0.2X +after 1900, rebase CORRECTED 12280 12280 0 8.1 122.8 0.2X +before 1900, rebase LEGACY 14178 14178 0 7.1 141.8 0.2X +before 1900, rebase CORRECTED 12140 12140 0 8.2 121.4 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Load TIMESTAMP_MILLIS from parquet: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1900, vec off, rebase EXCEPTION 13810 13860 66 7.2 138.1 1.0X +after 1900, vec off, rebase LEGACY 13932 13980 63 7.2 139.3 1.0X +after 1900, vec off, rebase CORRECTED 13910 13950 37 7.2 139.1 1.0X +after 1900, vec on, rebase EXCEPTION 4232 4263 38 23.6 42.3 3.3X +after 1900, vec on, rebase LEGACY 4752 4783 29 21.0 47.5 2.9X +after 1900, vec on, rebase CORRECTED 4344 4367 19 23.0 43.4 3.2X +before 1900, vec off, rebase LEGACY 16639 16685 45 6.0 166.4 0.8X +before 1900, vec off, rebase CORRECTED 13904 13946 44 7.2 139.0 1.0X +before 1900, vec on, rebase LEGACY 6832 6971 204 14.6 68.3 2.0X +before 1900, vec on, rebase CORRECTED 4436 4447 11 22.5 44.4 3.1X + + +================================================================================================ +Rebasing dates/timestamps in ORC datasource +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Save DATE to ORC: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1582, noop 9332 9332 0 10.7 93.3 1.0X +before 1582, noop 6370 6370 0 15.7 63.7 1.5X +after 1582 13178 13178 0 7.6 131.8 0.7X +before 1582 10497 10497 0 9.5 105.0 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Load DATE from ORC: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1582, vec off 9248 9287 40 10.8 92.5 1.0X +after 1582, vec on 2662 2673 9 37.6 26.6 3.5X +before 1582, vec off 9247 9270 23 10.8 92.5 1.0X +before 1582, vec on 2826 2828 2 35.4 28.3 3.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Save TIMESTAMP to ORC: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1900, noop 2278 2278 0 43.9 22.8 1.0X +before 1900, noop 2416 2416 0 41.4 24.2 0.9X +after 1900 11032 11032 0 9.1 110.3 0.2X +before 1900 12738 12738 0 7.9 127.4 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Load TIMESTAMP from ORC: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +after 1900, vec off 10660 10665 5 9.4 106.6 1.0X +after 1900, vec on 3943 3950 9 25.4 39.4 2.7X +before 1900, vec off 12734 12748 16 7.9 127.3 0.8X +before 1900, vec on 6114 6120 5 16.4 61.1 1.7X + + diff --git a/sql/core/benchmarks/EncodeBenchmark-jdk25-results.txt b/sql/core/benchmarks/EncodeBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..8268c41a52ed4 --- /dev/null +++ b/sql/core/benchmarks/EncodeBenchmark-jdk25-results.txt @@ -0,0 +1,8 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +encode: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +UTF-32 91992 92067 106 0.1 9199.2 1.0X +UTF-16 53943 54056 160 0.2 5394.3 1.7X +UTF-8 29762 29770 12 0.3 2976.2 3.1X + diff --git a/sql/core/benchmarks/ExternalAppendOnlyUnsafeRowArrayBenchmark-jdk25-results.txt b/sql/core/benchmarks/ExternalAppendOnlyUnsafeRowArrayBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..3ac39b59e2e96 --- /dev/null +++ b/sql/core/benchmarks/ExternalAppendOnlyUnsafeRowArrayBenchmark-jdk25-results.txt @@ -0,0 +1,45 @@ +================================================================================================ +WITHOUT SPILL +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Array with 100000 rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ArrayBuffer 2814 2880 93 36.4 27.5 1.0X +ExternalAppendOnlyUnsafeRowArray 4069 4147 110 25.2 39.7 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Array with 1000 rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ArrayBuffer 5092 5108 22 51.5 19.4 1.0X +ExternalAppendOnlyUnsafeRowArray 12319 12358 55 21.3 47.0 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Array with 30000 rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +ArrayBuffer 12620 12711 129 38.9 25.7 1.0X +ExternalAppendOnlyUnsafeRowArray 19962 20007 64 24.6 40.6 0.6X + + +================================================================================================ +WITH SPILL +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Spilling with 1000 rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +UnsafeExternalSorter 9745 9767 32 26.9 37.2 1.0X +ExternalAppendOnlyUnsafeRowArray 6339 6355 23 41.4 24.2 1.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Spilling with 10000 rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +UnsafeExternalSorter 5 5 1 31.9 31.3 1.0X +ExternalAppendOnlyUnsafeRowArray 4 4 0 38.4 26.0 1.2X + + diff --git a/sql/core/benchmarks/ExtractBenchmark-jdk25-results.txt b/sql/core/benchmarks/ExtractBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..318be38e024c0 --- /dev/null +++ b/sql/core/benchmarks/ExtractBenchmark-jdk25-results.txt @@ -0,0 +1,104 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Invoke extract for timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +cast to timestamp 257 279 19 38.9 25.7 1.0X +YEAR of timestamp 562 581 23 17.8 56.2 0.5X +YEAROFWEEK of timestamp 630 657 34 15.9 63.0 0.4X +QUARTER of timestamp 651 669 20 15.4 65.1 0.4X +MONTH of timestamp 570 593 36 17.6 57.0 0.5X +WEEK of timestamp 895 910 16 11.2 89.5 0.3X +DAY of timestamp 574 588 17 17.4 57.4 0.4X +DAYOFWEEK of timestamp 733 748 18 13.6 73.3 0.4X +DOW of timestamp 737 748 9 13.6 73.7 0.3X +DOW_ISO of timestamp 687 708 28 14.6 68.7 0.4X +DAYOFWEEK_ISO of timestamp 685 712 30 14.6 68.5 0.4X +DOY of timestamp 611 623 15 16.4 61.1 0.4X +HOUR of timestamp 441 452 17 22.7 44.1 0.6X +MINUTE of timestamp 439 449 11 22.8 43.9 0.6X +SECOND of timestamp 555 560 7 18.0 55.5 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Invoke date_part for timestamp: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +cast to timestamp 247 261 17 40.6 24.7 1.0X +YEAR of timestamp 562 575 16 17.8 56.2 0.4X +YEAROFWEEK of timestamp 626 645 19 16.0 62.6 0.4X +QUARTER of timestamp 647 655 12 15.4 64.7 0.4X +MONTH of timestamp 568 578 12 17.6 56.8 0.4X +WEEK of timestamp 881 886 4 11.3 88.1 0.3X +DAY of timestamp 573 583 11 17.5 57.3 0.4X +DAYOFWEEK of timestamp 731 738 6 13.7 73.1 0.3X +DOW of timestamp 733 748 18 13.6 73.3 0.3X +DOW_ISO of timestamp 686 692 6 14.6 68.6 0.4X +DAYOFWEEK_ISO of timestamp 688 700 14 14.5 68.8 0.4X +DOY of timestamp 607 611 5 16.5 60.7 0.4X +HOUR of timestamp 451 452 1 22.2 45.1 0.5X +MINUTE of timestamp 436 445 15 23.0 43.6 0.6X +SECOND of timestamp 529 536 10 18.9 52.9 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Invoke extract for date: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +cast to date 529 533 5 18.9 52.9 1.0X +YEAR of date 557 560 3 18.0 55.7 1.0X +YEAROFWEEK of date 629 631 4 15.9 62.9 0.8X +QUARTER of date 640 645 5 15.6 64.0 0.8X +MONTH of date 567 581 22 17.6 56.7 0.9X +WEEK of date 882 890 10 11.3 88.2 0.6X +DAY of date 567 574 7 17.6 56.7 0.9X +DAYOFWEEK of date 730 734 3 13.7 73.0 0.7X +DOW of date 730 730 1 13.7 73.0 0.7X +DOW_ISO of date 684 694 15 14.6 68.4 0.8X +DAYOFWEEK_ISO of date 683 686 2 14.6 68.3 0.8X +DOY of date 608 610 3 16.4 60.8 0.9X +HOUR of date 969 980 17 10.3 96.9 0.5X +MINUTE of date 972 980 10 10.3 97.2 0.5X +SECOND of date 1063 1064 2 9.4 106.3 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Invoke date_part for date: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +cast to date 530 531 1 18.9 53.0 1.0X +YEAR of date 557 559 2 17.9 55.7 1.0X +YEAROFWEEK of date 633 648 13 15.8 63.3 0.8X +QUARTER of date 640 641 2 15.6 64.0 0.8X +MONTH of date 563 566 2 17.8 56.3 0.9X +WEEK of date 883 885 3 11.3 88.3 0.6X +DAY of date 571 573 2 17.5 57.1 0.9X +DAYOFWEEK of date 731 731 0 13.7 73.1 0.7X +DOW of date 730 733 4 13.7 73.0 0.7X +DOW_ISO of date 686 688 2 14.6 68.6 0.8X +DAYOFWEEK_ISO of date 687 688 2 14.6 68.7 0.8X +DOY of date 608 609 1 16.5 60.8 0.9X +HOUR of date 969 972 3 10.3 96.9 0.5X +MINUTE of date 976 979 4 10.2 97.6 0.5X +SECOND of date 1063 1064 2 9.4 106.3 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Invoke extract for interval: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +cast to interval 743 745 3 13.5 74.3 1.0X +YEAR of interval 726 732 10 13.8 72.6 1.0X +MONTH of interval 729 738 9 13.7 72.9 1.0X +DAY of interval 722 746 40 13.9 72.2 1.0X +HOUR of interval 726 727 2 13.8 72.6 1.0X +MINUTE of interval 734 737 4 13.6 73.4 1.0X +SECOND of interval 780 781 1 12.8 78.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Invoke date_part for interval: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +cast to interval 744 748 6 13.4 74.4 1.0X +YEAR of interval 725 735 17 13.8 72.5 1.0X +MONTH of interval 725 729 3 13.8 72.5 1.0X +DAY of interval 719 721 3 13.9 71.9 1.0X +HOUR of interval 724 726 2 13.8 72.4 1.0X +MINUTE of interval 732 734 2 13.7 73.2 1.0X +SECOND of interval 778 781 4 12.9 77.8 1.0X + diff --git a/sql/core/benchmarks/FilterPushdownBenchmark-jdk25-results.txt b/sql/core/benchmarks/FilterPushdownBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..f428fa2ca3f13 --- /dev/null +++ b/sql/core/benchmarks/FilterPushdownBenchmark-jdk25-results.txt @@ -0,0 +1,734 @@ +================================================================================================ +Pushdown for many distinct value case +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 0 string row (value IS NULL): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 6528 6585 44 2.4 415.0 1.0X +Parquet Vectorized (Pushdown) 276 293 12 57.0 17.5 23.7X +Native ORC Vectorized 4787 4823 49 3.3 304.3 1.4X +Native ORC Vectorized (Pushdown) 320 333 8 49.2 20.3 20.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 0 string row ('7864320' < value < '7864320'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6493 6519 26 2.4 412.8 1.0X +Parquet Vectorized (Pushdown) 273 282 7 57.6 17.4 23.8X +Native ORC Vectorized 4883 4910 21 3.2 310.4 1.3X +Native ORC Vectorized (Pushdown) 312 331 12 50.5 19.8 20.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 string row (value = '7864320'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 6562 6594 27 2.4 417.2 1.0X +Parquet Vectorized (Pushdown) 267 273 7 59.0 17.0 24.6X +Native ORC Vectorized 4843 4867 28 3.2 307.9 1.4X +Native ORC Vectorized (Pushdown) 310 321 13 50.8 19.7 21.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 string row (value <=> '7864320'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6429 6453 14 2.4 408.7 1.0X +Parquet Vectorized (Pushdown) 253 264 10 62.2 16.1 25.4X +Native ORC Vectorized 4840 4850 14 3.2 307.7 1.3X +Native ORC Vectorized (Pushdown) 300 309 8 52.4 19.1 21.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 string row ('7864320' <= value <= '7864320'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6401 6447 41 2.5 407.0 1.0X +Parquet Vectorized (Pushdown) 253 259 7 62.3 16.1 25.3X +Native ORC Vectorized 4833 4841 10 3.3 307.3 1.3X +Native ORC Vectorized (Pushdown) 310 318 9 50.8 19.7 20.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select all string rows (value IS NOT NULL): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 12979 13050 56 1.2 825.2 1.0X +Parquet Vectorized (Pushdown) 13141 13190 36 1.2 835.5 1.0X +Native ORC Vectorized 11454 11511 46 1.4 728.2 1.1X +Native ORC Vectorized (Pushdown) 11575 11601 26 1.4 735.9 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 0 int row (value IS NULL): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 6195 6219 27 2.5 393.8 1.0X +Parquet Vectorized (Pushdown) 258 275 13 60.9 16.4 24.0X +Native ORC Vectorized 4474 4535 43 3.5 284.5 1.4X +Native ORC Vectorized (Pushdown) 289 304 14 54.4 18.4 21.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 0 int row (7864320 < value < 7864320): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6080 6098 20 2.6 386.5 1.0X +Parquet Vectorized (Pushdown) 253 261 8 62.2 16.1 24.0X +Native ORC Vectorized 4499 4501 2 3.5 286.0 1.4X +Native ORC Vectorized (Pushdown) 292 301 5 53.9 18.6 20.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 int row (value = 7864320): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 6183 6192 8 2.5 393.1 1.0X +Parquet Vectorized (Pushdown) 249 256 5 63.1 15.8 24.8X +Native ORC Vectorized 4518 4558 31 3.5 287.3 1.4X +Native ORC Vectorized (Pushdown) 292 301 6 53.8 18.6 21.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 int row (value <=> 7864320): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 6184 6198 11 2.5 393.2 1.0X +Parquet Vectorized (Pushdown) 250 253 4 63.0 15.9 24.8X +Native ORC Vectorized 4542 4590 29 3.5 288.8 1.4X +Native ORC Vectorized (Pushdown) 293 300 5 53.6 18.6 21.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 int row (7864320 <= value <= 7864320): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 6180 6192 10 2.5 392.9 1.0X +Parquet Vectorized (Pushdown) 251 254 4 62.7 15.9 24.6X +Native ORC Vectorized 4569 4608 24 3.4 290.5 1.4X +Native ORC Vectorized (Pushdown) 292 300 6 53.9 18.5 21.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 int row (7864319 < value < 7864321): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6177 6195 12 2.5 392.7 1.0X +Parquet Vectorized (Pushdown) 250 254 5 63.0 15.9 24.8X +Native ORC Vectorized 4555 4579 17 3.5 289.6 1.4X +Native ORC Vectorized (Pushdown) 292 298 3 53.8 18.6 21.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 10% int rows (value < 1572864): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 6826 6844 14 2.3 434.0 1.0X +Parquet Vectorized (Pushdown) 1512 1521 10 10.4 96.1 4.5X +Native ORC Vectorized 5148 5163 10 3.1 327.3 1.3X +Native ORC Vectorized (Pushdown) 1360 1367 12 11.6 86.4 5.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 50% int rows (value < 7864320): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 9205 9226 15 1.7 585.2 1.0X +Parquet Vectorized (Pushdown) 6286 6302 12 2.5 399.7 1.5X +Native ORC Vectorized 7576 7585 8 2.1 481.7 1.2X +Native ORC Vectorized (Pushdown) 5499 5533 20 2.9 349.6 1.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 90% int rows (value < 14155776): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 11585 11600 13 1.4 736.6 1.0X +Parquet Vectorized (Pushdown) 11029 11048 14 1.4 701.2 1.1X +Native ORC Vectorized 10205 10217 13 1.5 648.8 1.1X +Native ORC Vectorized (Pushdown) 9937 9955 15 1.6 631.8 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select all int rows (value IS NOT NULL): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 12185 12225 32 1.3 774.7 1.0X +Parquet Vectorized (Pushdown) 12290 12336 29 1.3 781.4 1.0X +Native ORC Vectorized 10629 10646 18 1.5 675.8 1.1X +Native ORC Vectorized (Pushdown) 10647 10660 12 1.5 676.9 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select all int rows (value > -1): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 12218 12230 8 1.3 776.8 1.0X +Parquet Vectorized (Pushdown) 12260 12288 27 1.3 779.4 1.0X +Native ORC Vectorized 10391 10413 15 1.5 660.7 1.2X +Native ORC Vectorized (Pushdown) 10520 10527 10 1.5 668.9 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select all int rows (value != -1): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 12308 12328 21 1.3 782.5 1.0X +Parquet Vectorized (Pushdown) 12367 12396 27 1.3 786.2 1.0X +Native ORC Vectorized 10443 10509 43 1.5 664.0 1.2X +Native ORC Vectorized (Pushdown) 10631 10636 5 1.5 675.9 1.2X + + +================================================================================================ +Pushdown for few distinct value case (use dictionary encoding) +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 0 distinct string row (value IS NULL): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5549 5580 34 2.8 352.8 1.0X +Parquet Vectorized (Pushdown) 211 244 19 74.6 13.4 26.3X +Native ORC Vectorized 6534 6590 45 2.4 415.4 0.8X +Native ORC Vectorized (Pushdown) 1011 1031 15 15.6 64.3 5.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 0 distinct string row ('100' < value < '100'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 5614 5646 25 2.8 356.9 1.0X +Parquet Vectorized (Pushdown) 213 220 5 73.9 13.5 26.4X +Native ORC Vectorized 6587 6600 13 2.4 418.8 0.9X +Native ORC Vectorized (Pushdown) 974 985 8 16.2 61.9 5.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 distinct string row (value = '100'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5569 5573 4 2.8 354.1 1.0X +Parquet Vectorized (Pushdown) 254 261 6 61.8 16.2 21.9X +Native ORC Vectorized 6582 6609 48 2.4 418.5 0.8X +Native ORC Vectorized (Pushdown) 1018 1024 5 15.5 64.7 5.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 distinct string row (value <=> '100'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 5575 5589 13 2.8 354.4 1.0X +Parquet Vectorized (Pushdown) 254 259 5 62.0 16.1 22.0X +Native ORC Vectorized 6573 6607 25 2.4 417.9 0.8X +Native ORC Vectorized (Pushdown) 1009 1022 8 15.6 64.1 5.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 distinct string row ('100' <= value <= '100'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5633 5649 19 2.8 358.1 1.0X +Parquet Vectorized (Pushdown) 257 260 3 61.3 16.3 21.9X +Native ORC Vectorized 6664 6677 13 2.4 423.7 0.8X +Native ORC Vectorized (Pushdown) 1029 1038 10 15.3 65.4 5.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select all distinct string rows (value IS NOT NULL): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 12929 13001 58 1.2 822.0 1.0X +Parquet Vectorized (Pushdown) 13058 13067 9 1.2 830.2 1.0X +Native ORC Vectorized 14182 14210 23 1.1 901.6 0.9X +Native ORC Vectorized (Pushdown) 14665 14877 123 1.1 932.4 0.9X + + +================================================================================================ +Pushdown benchmark for StringStartsWith +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +StringStartsWith filter: (value like '10%'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6826 6866 41 2.3 434.0 1.0X +Parquet Vectorized (Pushdown) 858 877 12 18.3 54.6 8.0X +Native ORC Vectorized 5277 5315 29 3.0 335.5 1.3X +Native ORC Vectorized (Pushdown) 5305 5314 12 3.0 337.3 1.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +StringStartsWith filter: (value like '1000%'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6436 6442 7 2.4 409.2 1.0X +Parquet Vectorized (Pushdown) 240 248 5 65.6 15.3 26.8X +Native ORC Vectorized 5013 5022 9 3.1 318.7 1.3X +Native ORC Vectorized (Pushdown) 5130 5144 17 3.1 326.1 1.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +StringStartsWith filter: (value like '786432%'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6408 6439 28 2.5 407.4 1.0X +Parquet Vectorized (Pushdown) 235 239 3 67.0 14.9 27.3X +Native ORC Vectorized 5000 5006 6 3.1 317.9 1.3X +Native ORC Vectorized (Pushdown) 5117 5124 5 3.1 325.3 1.3X + + +================================================================================================ +Pushdown benchmark for StringEndsWith +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +StringEndsWith filter: (value like '%10'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5608 5622 11 2.8 356.6 1.0X +Parquet Vectorized (Pushdown) 335 352 15 46.9 21.3 16.7X +Native ORC Vectorized 6617 6659 27 2.4 420.7 0.8X +Native ORC Vectorized (Pushdown) 6919 6939 25 2.3 439.9 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +StringEndsWith filter: (value like '%1000'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5469 5488 18 2.9 347.7 1.0X +Parquet Vectorized (Pushdown) 236 243 6 66.7 15.0 23.2X +Native ORC Vectorized 6521 6530 7 2.4 414.6 0.8X +Native ORC Vectorized (Pushdown) 6895 6901 4 2.3 438.4 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +StringEndsWith filter: (value like '%786432'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5461 5475 9 2.9 347.2 1.0X +Parquet Vectorized (Pushdown) 237 241 4 66.5 15.0 23.1X +Native ORC Vectorized 6519 6537 18 2.4 414.5 0.8X +Native ORC Vectorized (Pushdown) 6906 6920 11 2.3 439.1 0.8X + + +================================================================================================ +Pushdown benchmark for StringContains +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +StringContains filter: (value like '%10%'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5813 5847 29 2.7 369.6 1.0X +Parquet Vectorized (Pushdown) 788 801 18 20.0 50.1 7.4X +Native ORC Vectorized 6805 6842 61 2.3 432.7 0.9X +Native ORC Vectorized (Pushdown) 7178 7198 21 2.2 456.3 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +StringContains filter: (value like '%1000%'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5506 5541 27 2.9 350.1 1.0X +Parquet Vectorized (Pushdown) 237 245 6 66.4 15.1 23.2X +Native ORC Vectorized 6502 6520 17 2.4 413.4 0.8X +Native ORC Vectorized (Pushdown) 6874 6882 7 2.3 437.0 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +StringContains filter: (value like '%786432%'): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 5480 5507 22 2.9 348.4 1.0X +Parquet Vectorized (Pushdown) 240 244 3 65.5 15.3 22.8X +Native ORC Vectorized 6515 6545 20 2.4 414.2 0.8X +Native ORC Vectorized (Pushdown) 6890 6915 21 2.3 438.1 0.8X + + +================================================================================================ +Pushdown benchmark for decimal +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 decimal(9, 2) row (value = 7864320): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 2431 2454 28 6.5 154.6 1.0X +Parquet Vectorized (Pushdown) 64 73 8 246.6 4.1 38.1X +Native ORC Vectorized 3036 3049 18 5.2 193.0 0.8X +Native ORC Vectorized (Pushdown) 59 66 5 265.9 3.8 41.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 10% decimal(9, 2) rows (value < 1572864): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 3722 3747 24 4.2 236.6 1.0X +Parquet Vectorized (Pushdown) 1806 1815 12 8.7 114.8 2.1X +Native ORC Vectorized 4361 4373 13 3.6 277.2 0.9X +Native ORC Vectorized (Pushdown) 1974 1978 4 8.0 125.5 1.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 50% decimal(9, 2) rows (value < 7864320): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 7822 7850 27 2.0 497.3 1.0X +Parquet Vectorized (Pushdown) 7521 7546 30 2.1 478.2 1.0X +Native ORC Vectorized 8881 8904 16 1.8 564.6 0.9X +Native ORC Vectorized (Pushdown) 8493 8521 19 1.9 540.0 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 90% decimal(9, 2) rows (value < 14155776): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 8755 8771 15 1.8 556.6 1.0X +Parquet Vectorized (Pushdown) 8762 8786 19 1.8 557.1 1.0X +Native ORC Vectorized 9834 9879 46 1.6 625.2 0.9X +Native ORC Vectorized (Pushdown) 9833 9861 20 1.6 625.2 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 decimal(18, 2) row (value = 7864320): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 2629 2647 19 6.0 167.1 1.0X +Parquet Vectorized (Pushdown) 63 72 8 251.5 4.0 42.0X +Native ORC Vectorized 3047 3063 15 5.2 193.7 0.9X +Native ORC Vectorized (Pushdown) 57 66 4 273.9 3.7 45.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 10% decimal(18, 2) rows (value < 1572864): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 3269 3280 9 4.8 207.8 1.0X +Parquet Vectorized (Pushdown) 946 958 16 16.6 60.2 3.5X +Native ORC Vectorized 3744 3752 7 4.2 238.0 0.9X +Native ORC Vectorized (Pushdown) 1026 1031 3 15.3 65.2 3.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 50% decimal(18, 2) rows (value < 7864320): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5822 5862 51 2.7 370.1 1.0X +Parquet Vectorized (Pushdown) 4546 4557 8 3.5 289.0 1.3X +Native ORC Vectorized 6464 6472 11 2.4 411.0 0.9X +Native ORC Vectorized (Pushdown) 4920 4938 15 3.2 312.8 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 90% decimal(18, 2) rows (value < 14155776): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 8298 8325 24 1.9 527.5 1.0X +Parquet Vectorized (Pushdown) 8072 8084 18 1.9 513.2 1.0X +Native ORC Vectorized 9190 9206 11 1.7 584.3 0.9X +Native ORC Vectorized (Pushdown) 8909 8925 19 1.8 566.4 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 decimal(38, 2) row (value = 7864320): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 3820 3832 9 4.1 242.9 1.0X +Parquet Vectorized (Pushdown) 68 74 4 232.3 4.3 56.4X +Native ORC Vectorized 3048 3055 6 5.2 193.8 1.3X +Native ORC Vectorized (Pushdown) 56 65 7 280.4 3.6 68.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 10% decimal(38, 2) rows (value < 1572864): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 4644 4667 24 3.4 295.3 1.0X +Parquet Vectorized (Pushdown) 1268 1273 6 12.4 80.6 3.7X +Native ORC Vectorized 3832 3843 14 4.1 243.6 1.2X +Native ORC Vectorized (Pushdown) 1127 1129 2 14.0 71.6 4.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 50% decimal(38, 2) rows (value < 7864320): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 8032 8041 8 2.0 510.7 1.0X +Parquet Vectorized (Pushdown) 6186 6200 12 2.5 393.3 1.3X +Native ORC Vectorized 6962 6973 18 2.3 442.6 1.2X +Native ORC Vectorized (Pushdown) 5423 5428 4 2.9 344.8 1.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 90% decimal(38, 2) rows (value < 14155776): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 11330 11349 32 1.4 720.3 1.0X +Parquet Vectorized (Pushdown) 11002 11021 17 1.4 699.5 1.0X +Native ORC Vectorized 10012 10063 44 1.6 636.6 1.1X +Native ORC Vectorized (Pushdown) 9743 9787 43 1.6 619.4 1.2X + + +================================================================================================ +Pushdown benchmark for InSet -> InFilters +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 5, distribution: 10): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6219 6252 43 2.5 395.4 1.0X +Parquet Vectorized (Pushdown) 287 296 6 54.8 18.3 21.7X +Native ORC Vectorized 4523 4545 14 3.5 287.5 1.4X +Native ORC Vectorized (Pushdown) 298 312 17 52.8 19.0 20.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 5, distribution: 50): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6246 6297 59 2.5 397.1 1.0X +Parquet Vectorized (Pushdown) 249 261 12 63.1 15.9 25.1X +Native ORC Vectorized 4500 4567 86 3.5 286.1 1.4X +Native ORC Vectorized (Pushdown) 305 310 3 51.5 19.4 20.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 5, distribution: 90): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6172 6218 52 2.5 392.4 1.0X +Parquet Vectorized (Pushdown) 251 254 3 62.8 15.9 24.6X +Native ORC Vectorized 4482 4492 7 3.5 285.0 1.4X +Native ORC Vectorized (Pushdown) 295 302 7 53.3 18.8 20.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 10, distribution: 10): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6136 6155 21 2.6 390.1 1.0X +Parquet Vectorized (Pushdown) 259 263 3 60.8 16.4 23.7X +Native ORC Vectorized 4493 4501 9 3.5 285.6 1.4X +Native ORC Vectorized (Pushdown) 306 310 6 51.5 19.4 20.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 10, distribution: 50): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6145 6154 11 2.6 390.7 1.0X +Parquet Vectorized (Pushdown) 265 270 5 59.4 16.8 23.2X +Native ORC Vectorized 4491 4501 11 3.5 285.5 1.4X +Native ORC Vectorized (Pushdown) 305 309 6 51.7 19.4 20.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 10, distribution: 90): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6117 6140 23 2.6 388.9 1.0X +Parquet Vectorized (Pushdown) 265 271 9 59.4 16.8 23.1X +Native ORC Vectorized 4481 4490 11 3.5 284.9 1.4X +Native ORC Vectorized (Pushdown) 305 310 6 51.6 19.4 20.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 50, distribution: 10): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6323 6353 22 2.5 402.0 1.0X +Parquet Vectorized (Pushdown) 816 819 5 19.3 51.9 7.8X +Native ORC Vectorized 4680 4690 9 3.4 297.6 1.4X +Native ORC Vectorized (Pushdown) 416 425 8 37.8 26.5 15.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 50, distribution: 50): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6320 6328 9 2.5 401.8 1.0X +Parquet Vectorized (Pushdown) 3158 3173 13 5.0 200.8 2.0X +Native ORC Vectorized 4673 4689 32 3.4 297.1 1.4X +Native ORC Vectorized (Pushdown) 419 427 8 37.6 26.6 15.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 50, distribution: 90): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6323 6336 10 2.5 402.0 1.0X +Parquet Vectorized (Pushdown) 5362 5383 18 2.9 340.9 1.2X +Native ORC Vectorized 4676 4692 27 3.4 297.3 1.4X +Native ORC Vectorized (Pushdown) 431 435 3 36.5 27.4 14.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 100, distribution: 10): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6322 6332 13 2.5 401.9 1.0X +Parquet Vectorized (Pushdown) 848 850 2 18.6 53.9 7.5X +Native ORC Vectorized 4660 4661 1 3.4 296.3 1.4X +Native ORC Vectorized (Pushdown) 506 512 8 31.1 32.1 12.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 100, distribution: 50): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6300 6322 15 2.5 400.6 1.0X +Parquet Vectorized (Pushdown) 3263 3275 15 4.8 207.4 1.9X +Native ORC Vectorized 4634 4644 11 3.4 294.6 1.4X +Native ORC Vectorized (Pushdown) 567 572 3 27.8 36.0 11.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +InSet -> InFilters (values count: 100, distribution: 90): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6311 6330 23 2.5 401.3 1.0X +Parquet Vectorized (Pushdown) 5592 5615 21 2.8 355.5 1.1X +Native ORC Vectorized 4628 4634 6 3.4 294.2 1.4X +Native ORC Vectorized (Pushdown) 571 577 4 27.6 36.3 11.1X + + +================================================================================================ +Pushdown benchmark for tinyint +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 tinyint row (value = CAST(63 AS tinyint)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 2729 2752 22 5.8 173.5 1.0X +Parquet Vectorized (Pushdown) 97 104 11 162.9 6.1 28.3X +Native ORC Vectorized 1941 1962 22 8.1 123.4 1.4X +Native ORC Vectorized (Pushdown) 117 124 13 134.3 7.4 23.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 10% tinyint rows (value < CAST(12 AS tinyint)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 3315 3354 46 4.7 210.8 1.0X +Parquet Vectorized (Pushdown) 856 909 43 18.4 54.5 3.9X +Native ORC Vectorized 2438 2445 6 6.5 155.0 1.4X +Native ORC Vectorized (Pushdown) 783 790 7 20.1 49.8 4.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 50% tinyint rows (value < CAST(63 AS tinyint)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5410 5442 22 2.9 343.9 1.0X +Parquet Vectorized (Pushdown) 4115 4133 14 3.8 261.6 1.3X +Native ORC Vectorized 4540 4554 18 3.5 288.6 1.2X +Native ORC Vectorized (Pushdown) 3623 3628 4 4.3 230.4 1.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 90% tinyint rows (value < CAST(114 AS tinyint)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 7611 7625 13 2.1 483.9 1.0X +Parquet Vectorized (Pushdown) 7398 7447 74 2.1 470.4 1.0X +Native ORC Vectorized 6913 6932 17 2.3 439.5 1.1X +Native ORC Vectorized (Pushdown) 6749 6763 11 2.3 429.1 1.1X + + +================================================================================================ +Pushdown benchmark for Timestamp +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 timestamp stored as INT96 row (value = timestamp_seconds(7864320)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 3073 3096 31 5.1 195.4 1.0X +Parquet Vectorized (Pushdown) 3084 3098 15 5.1 196.1 1.0X +Native ORC Vectorized 1813 1821 9 8.7 115.3 1.7X +Native ORC Vectorized (Pushdown) 40 44 5 396.6 2.5 77.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 10% timestamp stored as INT96 rows (value < timestamp_seconds(1572864)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 3653 3679 26 4.3 232.2 1.0X +Parquet Vectorized (Pushdown) 3659 3669 8 4.3 232.6 1.0X +Native ORC Vectorized 2397 2402 5 6.6 152.4 1.5X +Native ORC Vectorized (Pushdown) 802 805 3 19.6 51.0 4.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 50% timestamp stored as INT96 rows (value < timestamp_seconds(7864320)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 6050 6067 14 2.6 384.6 1.0X +Parquet Vectorized (Pushdown) 6047 6067 19 2.6 384.5 1.0X +Native ORC Vectorized 4894 4903 9 3.2 311.2 1.2X +Native ORC Vectorized (Pushdown) 3962 3974 9 4.0 251.9 1.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 90% timestamp stored as INT96 rows (value < timestamp_seconds(14155776)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 8387 8407 27 1.9 533.2 1.0X +Parquet Vectorized (Pushdown) 8355 8387 22 1.9 531.2 1.0X +Native ORC Vectorized 7014 7026 8 2.2 445.9 1.2X +Native ORC Vectorized (Pushdown) 6836 6852 21 2.3 434.6 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 timestamp stored as TIMESTAMP_MICROS row (value = timestamp_seconds(7864320)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 2620 2640 18 6.0 166.6 1.0X +Parquet Vectorized (Pushdown) 62 65 5 254.1 3.9 42.3X +Native ORC Vectorized 1821 1825 2 8.6 115.8 1.4X +Native ORC Vectorized (Pushdown) 41 44 4 382.3 2.6 63.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 10% timestamp stored as TIMESTAMP_MICROS rows (value < timestamp_seconds(1572864)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 3171 3202 37 5.0 201.6 1.0X +Parquet Vectorized (Pushdown) 909 913 4 17.3 57.8 3.5X +Native ORC Vectorized 2412 2418 8 6.5 153.4 1.3X +Native ORC Vectorized (Pushdown) 816 820 3 19.3 51.8 3.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 50% timestamp stored as TIMESTAMP_MICROS rows (value < timestamp_seconds(7864320)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5572 5587 11 2.8 354.3 1.0X +Parquet Vectorized (Pushdown) 4345 4359 21 3.6 276.2 1.3X +Native ORC Vectorized 4896 4904 8 3.2 311.3 1.1X +Native ORC Vectorized (Pushdown) 3981 3989 8 4.0 253.1 1.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 90% timestamp stored as TIMESTAMP_MICROS rows (value < timestamp_seconds(14155776)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 7880 7898 19 2.0 501.0 1.0X +Parquet Vectorized (Pushdown) 7652 7665 14 2.1 486.5 1.0X +Native ORC Vectorized 7019 7035 19 2.2 446.3 1.1X +Native ORC Vectorized (Pushdown) 6840 6849 6 2.3 434.9 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 timestamp stored as TIMESTAMP_MILLIS row (value = timestamp_seconds(7864320)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 2634 2641 8 6.0 167.5 1.0X +Parquet Vectorized (Pushdown) 62 68 6 253.6 3.9 42.5X +Native ORC Vectorized 1820 1823 2 8.6 115.7 1.4X +Native ORC Vectorized (Pushdown) 41 48 6 386.5 2.6 64.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 10% timestamp stored as TIMESTAMP_MILLIS rows (value < timestamp_seconds(1572864)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 3187 3200 11 4.9 202.6 1.0X +Parquet Vectorized (Pushdown) 900 926 41 17.5 57.2 3.5X +Native ORC Vectorized 2401 2407 3 6.6 152.7 1.3X +Native ORC Vectorized (Pushdown) 813 816 4 19.4 51.7 3.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 50% timestamp stored as TIMESTAMP_MILLIS rows (value < timestamp_seconds(7864320)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 5615 5632 12 2.8 357.0 1.0X +Parquet Vectorized (Pushdown) 4375 4388 10 3.6 278.1 1.3X +Native ORC Vectorized 4900 4908 6 3.2 311.5 1.1X +Native ORC Vectorized (Pushdown) 3962 3979 14 4.0 251.9 1.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 90% timestamp stored as TIMESTAMP_MILLIS rows (value < timestamp_seconds(14155776)): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +Parquet Vectorized 7932 7946 10 2.0 504.3 1.0X +Parquet Vectorized (Pushdown) 7725 7755 24 2.0 491.1 1.0X +Native ORC Vectorized 7007 7031 15 2.2 445.5 1.1X +Native ORC Vectorized (Pushdown) 6850 6869 12 2.3 435.5 1.2X + + +================================================================================================ +Pushdown benchmark with many filters +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 row with 1 filters: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 46 49 3 0.0 46498210.0 1.0X +Parquet Vectorized (Pushdown) 47 50 4 0.0 46910582.0 1.0X +Native ORC Vectorized 43 46 4 0.0 43216110.0 1.1X +Native ORC Vectorized (Pushdown) 49 52 4 0.0 48828556.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 row with 250 filters: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 165 169 4 0.0 164988090.0 1.0X +Parquet Vectorized (Pushdown) 168 176 7 0.0 168298571.0 1.0X +Native ORC Vectorized 163 171 7 0.0 163071465.0 1.0X +Native ORC Vectorized (Pushdown) 168 173 4 0.0 168465564.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select 1 row with 500 filters: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Parquet Vectorized 519 527 10 0.0 518531549.0 1.0X +Parquet Vectorized (Pushdown) 538 547 8 0.0 538124216.0 1.0X +Native ORC Vectorized 514 532 18 0.0 514298118.0 1.0X +Native ORC Vectorized (Pushdown) 526 545 19 0.0 526326806.0 1.0X + + diff --git a/sql/core/benchmarks/GenerateExecBenchmark-jdk25-results.txt b/sql/core/benchmarks/GenerateExecBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..9b309ebde76ca --- /dev/null +++ b/sql/core/benchmarks/GenerateExecBenchmark-jdk25-results.txt @@ -0,0 +1,12 @@ +================================================================================================ +GenerateExec benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +GenerateExec Benchmark: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +GenerateExec Benchmark wholestage off 72419 72574 218 1.4 724.2 1.0X +GenerateExec Benchmark wholestage on 19549 19662 98 5.1 195.5 3.7X + + diff --git a/sql/core/benchmarks/HashedRelationMetricsBenchmark-jdk25-results.txt b/sql/core/benchmarks/HashedRelationMetricsBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..fe13721c98662 --- /dev/null +++ b/sql/core/benchmarks/HashedRelationMetricsBenchmark-jdk25-results.txt @@ -0,0 +1,11 @@ +================================================================================================ +LongToUnsafeRowMap metrics +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +LongToUnsafeRowMap metrics: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +LongToUnsafeRowMap 447 462 14 1.1 894.6 1.0X + + diff --git a/sql/core/benchmarks/InExpressionBenchmark-jdk25-results.txt b/sql/core/benchmarks/InExpressionBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..4e39a7c369f3b --- /dev/null +++ b/sql/core/benchmarks/InExpressionBenchmark-jdk25-results.txt @@ -0,0 +1,740 @@ +================================================================================================ +In Expression Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 bytes: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 38 49 9 266.1 3.8 1.0X +InSet expression 71 78 6 141.2 7.1 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 bytes: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 37 42 5 271.3 3.7 1.0X +InSet expression 68 72 3 147.4 6.8 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 bytes: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 61 66 5 163.8 6.1 1.0X +InSet expression 89 93 4 111.9 8.9 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 bytes: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 101 106 5 99.4 10.1 1.0X +InSet expression 104 110 4 96.1 10.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 bytes: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 179 183 3 55.8 17.9 1.0X +InSet expression 131 137 4 76.4 13.1 1.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 bytes: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 357 365 8 28.0 35.7 1.0X +InSet expression 238 250 14 42.1 23.8 1.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 shorts: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 34 38 4 297.5 3.4 1.0X +InSet expression 90 97 5 110.6 9.0 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 shorts: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 41 45 4 243.6 4.1 1.0X +InSet expression 110 117 6 90.6 11.0 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 shorts: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 63 66 3 158.5 6.3 1.0X +InSet expression 109 113 2 91.5 10.9 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 shorts: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 106 108 2 94.1 10.6 1.0X +InSet expression 167 170 3 59.8 16.7 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 shorts: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 178 181 3 56.2 17.8 1.0X +InSet expression 162 168 8 61.6 16.2 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 shorts: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 330 331 2 30.3 33.0 1.0X +InSet expression 174 185 14 57.3 17.4 1.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +300 shorts: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 481 485 3 20.8 48.1 1.0X +InSet expression 187 193 6 53.4 18.7 2.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +400 shorts: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 637 638 1 15.7 63.7 1.0X +InSet expression 200 206 3 50.0 20.0 3.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +500 shorts: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 801 809 8 12.5 80.1 1.0X +InSet expression 215 222 6 46.5 21.5 3.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 shorts (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 29 33 4 347.4 2.9 1.0X +InSet expression 86 89 3 115.8 8.6 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 shorts (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 36 42 4 277.8 3.6 1.0X +InSet expression 110 115 3 90.9 11.0 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 shorts (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 61 64 3 164.0 6.1 1.0X +InSet expression 148 153 6 67.4 14.8 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 shorts (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 102 105 3 97.8 10.2 1.0X +InSet expression 175 183 7 57.3 17.5 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 shorts (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 182 185 4 54.9 18.2 1.0X +InSet expression 165 170 6 60.6 16.5 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 shorts (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 342 346 4 29.3 34.2 1.0X +InSet expression 173 178 5 58.0 17.3 2.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +300 shorts (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 489 496 8 20.4 48.9 1.0X +InSet expression 187 195 10 53.6 18.7 2.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +400 shorts (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 643 650 10 15.6 64.3 1.0X +InSet expression 201 207 5 49.7 20.1 3.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +500 shorts (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 824 825 1 12.1 82.4 1.0X +InSet expression 216 222 6 46.2 21.6 3.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 ints: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 30 33 4 332.9 3.0 1.0X +InSet expression 99 104 5 100.7 9.9 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 ints: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 40 43 3 251.0 4.0 1.0X +InSet expression 120 126 7 83.1 12.0 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 ints: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 60 63 4 165.5 6.0 1.0X +InSet expression 121 127 6 82.7 12.1 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 ints: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 102 104 2 98.0 10.2 1.0X +InSet expression 181 186 6 55.4 18.1 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 ints: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 178 180 3 56.3 17.8 1.0X +InSet expression 179 186 5 55.8 17.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 ints: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 328 332 4 30.4 32.8 1.0X +InSet expression 190 194 6 52.7 19.0 1.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +300 ints: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 490 493 4 20.4 49.0 1.0X +InSet expression 205 210 4 48.7 20.5 2.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +400 ints: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 640 644 4 15.6 64.0 1.0X +InSet expression 220 230 12 45.4 22.0 2.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +500 ints: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 791 796 3 12.6 79.1 1.0X +InSet expression 233 237 3 43.0 23.3 3.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 ints (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 27 29 3 374.3 2.7 1.0X +InSet expression 98 101 3 102.4 9.8 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 ints (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 39 42 3 258.1 3.9 1.0X +InSet expression 118 124 4 84.4 11.8 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 ints (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 86 89 2 115.9 8.6 1.0X +InSet expression 134 141 8 74.4 13.4 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 ints (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 156 157 2 64.1 15.6 1.0X +InSet expression 175 180 7 57.1 17.5 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 ints (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 297 302 7 33.7 29.7 1.0X +InSet expression 171 176 5 58.5 17.1 1.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 ints (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 596 602 9 16.8 59.6 1.0X +InSet expression 179 185 7 55.8 17.9 3.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +300 ints (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 882 885 4 11.3 88.2 1.0X +InSet expression 191 197 4 52.4 19.1 4.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +400 ints (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 1041 1053 7 9.6 104.1 1.0X +InSet expression 204 208 3 49.0 20.4 5.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +500 ints (non-compact): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 1292 1323 58 7.7 129.2 1.0X +InSet expression 217 223 9 46.1 21.7 6.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 longs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 29 32 3 339.1 2.9 1.0X +InSet expression 88 92 6 113.1 8.8 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 longs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 37 40 3 267.6 3.7 1.0X +InSet expression 106 110 4 94.2 10.6 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 longs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 58 62 9 171.8 5.8 1.0X +InSet expression 108 112 3 92.4 10.8 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 longs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 97 101 4 103.0 9.7 1.0X +InSet expression 163 169 8 61.4 16.3 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 longs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 171 174 5 58.6 17.1 1.0X +InSet expression 161 168 7 62.0 16.1 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 longs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 319 323 5 31.4 31.9 1.0X +InSet expression 166 171 6 60.3 16.6 1.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 floats: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 40 44 3 252.8 4.0 1.0X +InSet expression 91 94 2 109.7 9.1 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 floats: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 62 64 3 161.2 6.2 1.0X +InSet expression 120 123 3 83.2 12.0 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 floats: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 129 137 5 77.3 12.9 1.0X +InSet expression 118 123 5 84.8 11.8 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 floats: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 275 278 4 36.4 27.5 1.0X +InSet expression 187 189 2 53.5 18.7 1.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 floats: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 477 482 5 21.0 47.7 1.0X +InSet expression 157 163 8 63.8 15.7 3.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 floats: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 2021 2042 45 4.9 202.1 1.0X +InSet expression 158 162 3 63.1 15.8 12.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 doubles: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 39 41 2 259.4 3.9 1.0X +InSet expression 84 88 3 119.4 8.4 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 doubles: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 61 63 3 163.8 6.1 1.0X +InSet expression 106 109 3 94.4 10.6 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 doubles: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 128 131 3 78.0 12.8 1.0X +InSet expression 109 112 3 91.7 10.9 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 doubles: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 277 279 2 36.1 27.7 1.0X +InSet expression 169 172 3 59.1 16.9 1.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 doubles: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 475 478 3 21.1 47.5 1.0X +InSet expression 145 150 3 68.8 14.5 3.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 doubles: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 2258 2293 64 4.4 225.8 1.0X +InSet expression 153 157 4 65.2 15.3 14.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 small decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 20 23 2 49.4 20.3 1.0X +InSet expression 53 57 3 18.8 53.1 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 small decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 26 28 2 38.5 26.0 1.0X +InSet expression 56 59 3 18.0 55.7 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 small decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 41 46 4 24.4 41.0 1.0X +InSet expression 57 60 3 17.7 56.6 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 small decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 79 85 6 12.6 79.4 1.0X +InSet expression 63 66 3 15.9 63.0 1.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 small decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 243 244 2 4.1 242.5 1.0X +InSet expression 61 64 3 16.5 60.6 4.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 small decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 575 579 4 1.7 574.5 1.0X +InSet expression 64 66 3 15.7 63.8 9.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 large decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 6 7 2 177.0 5.7 1.0X +InSet expression 6 7 2 181.4 5.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 large decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 5 7 2 187.8 5.3 1.0X +InSet expression 5 6 2 199.0 5.0 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 large decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 6 7 2 178.2 5.6 1.0X +InSet expression 6 7 2 180.6 5.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 large decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 7 9 2 151.3 6.6 1.0X +InSet expression 7 9 2 151.2 6.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 large decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 9 10 2 117.4 8.5 1.0X +InSet expression 8 10 2 118.5 8.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 large decimals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 12 14 3 81.6 12.3 1.0X +InSet expression 12 14 2 84.8 11.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 strings: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 28 30 2 35.9 27.8 1.0X +InSet expression 46 49 3 21.5 46.5 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 strings: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 30 32 3 33.1 30.2 1.0X +InSet expression 49 51 2 20.4 48.9 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 strings: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 45 48 4 22.4 44.7 1.0X +InSet expression 54 58 3 18.6 53.7 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 strings: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 68 70 2 14.7 67.8 1.0X +InSet expression 57 60 3 17.5 57.1 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 strings: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 114 119 3 8.7 114.3 1.0X +InSet expression 55 58 3 18.2 55.1 2.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 strings: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 494 495 1 2.0 494.5 1.0X +InSet expression 56 58 2 17.9 55.9 8.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 timestamps: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 17 19 2 598.5 1.7 1.0X +InSet expression 80 84 3 124.2 8.0 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 timestamps: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 26 29 3 386.6 2.6 1.0X +InSet expression 95 98 3 105.7 9.5 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 timestamps: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 46 48 2 215.1 4.6 1.0X +InSet expression 135 138 3 74.3 13.5 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 timestamps: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 80 82 2 125.5 8.0 1.0X +InSet expression 174 177 3 57.5 17.4 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 timestamps: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 152 155 5 65.8 15.2 1.0X +InSet expression 158 163 6 63.4 15.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 timestamps: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 294 300 6 34.0 29.4 1.0X +InSet expression 158 164 5 63.4 15.8 1.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 dates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 297 303 5 33.6 29.7 1.0X +InSet expression 294 298 4 34.1 29.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 dates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 294 300 5 34.0 29.4 1.0X +InSet expression 293 301 6 34.1 29.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 dates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 303 307 3 33.0 30.3 1.0X +InSet expression 297 300 3 33.6 29.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 dates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 346 348 2 28.9 34.6 1.0X +InSet expression 294 300 5 34.0 29.4 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 dates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 433 437 3 23.1 43.3 1.0X +InSet expression 299 302 4 33.5 29.9 1.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 dates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 691 692 1 14.5 69.1 1.0X +InSet expression 297 306 5 33.6 29.7 2.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +300 dates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 909 929 12 11.0 90.9 1.0X +InSet expression 301 307 4 33.2 30.1 3.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +400 dates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 1064 1078 13 9.4 106.4 1.0X +InSet expression 300 308 14 33.3 30.0 3.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +500 dates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 1275 1285 7 7.8 127.5 1.0X +InSet expression 401 409 6 24.9 40.1 3.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 arrays: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 26 29 3 38.5 26.0 1.0X +InSet expression 54 56 2 18.4 54.2 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 arrays: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 41 47 5 24.1 41.5 1.0X +InSet expression 80 82 2 12.5 79.8 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 arrays: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 159 162 3 6.3 158.8 1.0X +InSet expression 93 98 5 10.7 93.4 1.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 arrays: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 397 406 9 2.5 397.4 1.0X +InSet expression 120 124 3 8.3 120.1 3.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 arrays: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 793 802 12 1.3 793.5 1.0X +InSet expression 135 139 5 7.4 134.9 5.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 arrays: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 1741 1875 285 0.6 1741.5 1.0X +InSet expression 151 157 5 6.6 150.9 11.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +5 structs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 18 20 2 56.6 17.7 1.0X +InSet expression 96 99 3 10.4 96.2 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +10 structs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 24 27 3 41.8 23.9 1.0X +InSet expression 146 153 7 6.9 146.0 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +25 structs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 69 72 3 14.6 68.5 1.0X +InSet expression 173 179 10 5.8 172.6 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +50 structs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 179 183 4 5.6 178.6 1.0X +InSet expression 223 227 3 4.5 223.1 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +100 structs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 459 464 4 2.2 459.2 1.0X +InSet expression 252 254 2 4.0 251.9 1.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +200 structs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +In expression 1248 1346 208 0.8 1248.0 1.0X +InSet expression 282 288 5 3.5 282.0 4.4X + + diff --git a/sql/core/benchmarks/InMemoryColumnarBenchmark-jdk25-results.txt b/sql/core/benchmarks/InMemoryColumnarBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..c39ed4ca4d159 --- /dev/null +++ b/sql/core/benchmarks/InMemoryColumnarBenchmark-jdk25-results.txt @@ -0,0 +1,12 @@ +================================================================================================ +Int In-memory with 1000000 rows +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Int In-Memory scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +columnar deserialization + columnar-to-row 170 213 73 5.9 169.7 1.0X +row-based deserialization 145 201 96 6.9 144.8 1.2X + + diff --git a/sql/core/benchmarks/InsertTableWithDynamicPartitionsBenchmark-jdk25-results.txt b/sql/core/benchmarks/InsertTableWithDynamicPartitionsBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..fb94fcbf1c37f --- /dev/null +++ b/sql/core/benchmarks/InsertTableWithDynamicPartitionsBenchmark-jdk25-results.txt @@ -0,0 +1,8 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +dynamic insert table benchmark, totalRows = 200000: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------------- +one partition column, 100 partitions 8594 8599 7 0.0 42972.2 1.0X +two partition columns, 500 partitions 23499 23673 246 0.0 117494.5 0.4X +three partition columns, 2000 partitions 67398 67403 7 0.0 336991.4 0.1X + diff --git a/sql/core/benchmarks/IntervalBenchmark-jdk25-results.txt b/sql/core/benchmarks/IntervalBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..163fd4325b911 --- /dev/null +++ b/sql/core/benchmarks/IntervalBenchmark-jdk25-results.txt @@ -0,0 +1,40 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +cast strings to intervals: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +prepare string w/ interval 329 333 3 3.0 329.0 1.0X +prepare string w/o interval 319 320 1 3.1 318.9 1.0X +1 units w/ interval 305 316 12 3.3 305.0 1.1X +1 units w/o interval 307 308 1 3.3 307.1 1.1X +2 units w/ interval 507 515 9 2.0 506.9 0.6X +2 units w/o interval 493 494 1 2.0 493.0 0.7X +3 units w/ interval 1240 1246 5 0.8 1239.8 0.3X +3 units w/o interval 1210 1211 1 0.8 1209.9 0.3X +4 units w/ interval 1419 1432 14 0.7 1419.5 0.2X +4 units w/o interval 1393 1398 7 0.7 1392.6 0.2X +5 units w/ interval 1583 1586 4 0.6 1582.8 0.2X +5 units w/o interval 1559 1561 1 0.6 1559.3 0.2X +6 units w/ interval 1746 1748 4 0.6 1745.9 0.2X +6 units w/o interval 1727 1733 6 0.6 1727.3 0.2X +7 units w/ interval 2319 2324 6 0.4 2318.9 0.1X +7 units w/o interval 2315 2318 3 0.4 2315.4 0.1X +8 units w/ interval 2463 2466 3 0.4 2463.1 0.1X +8 units w/o interval 2445 2446 2 0.4 2444.8 0.1X +9 units w/ interval 2723 2726 3 0.4 2722.7 0.1X +9 units w/o interval 2714 2719 4 0.4 2714.3 0.1X +10 units w/ interval 2979 2981 2 0.3 2979.2 0.1X +10 units w/o interval 2965 2970 5 0.3 2965.1 0.1X +11 units w/ interval 3244 3250 6 0.3 3244.4 0.1X +11 units w/o interval 3242 3242 1 0.3 3241.8 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +make_interval(): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +prepare make_interval() 338 341 3 3.0 338.2 1.0X +make_interval(0, 1, 2, 3, 4, 5, 50.123456) 44 44 0 22.9 43.6 7.8X +make_interval(*, *, 2, 3, 4, 5, 50.123456) 50 51 1 20.2 49.6 6.8X +make_interval(0, 1, *, *, 4, 5, 50.123456) 48 49 0 20.7 48.3 7.0X +make_interval(0, 1, 2, 3, *, *, *) 315 317 1 3.2 315.0 1.1X +make_interval(*, *, *, *, *, *, *) 325 330 5 3.1 324.8 1.0X + diff --git a/sql/core/benchmarks/JoinBenchmark-jdk25-results.txt b/sql/core/benchmarks/JoinBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..81f08648eff45 --- /dev/null +++ b/sql/core/benchmarks/JoinBenchmark-jdk25-results.txt @@ -0,0 +1,82 @@ +================================================================================================ +Join Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Join w long: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Join w long wholestage off 2267 2278 16 9.3 108.1 1.0X +Join w long wholestage on 912 928 19 23.0 43.5 2.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Join w long duplicated: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Join w long duplicated wholestage off 2169 2177 11 9.7 103.4 1.0X +Join w long duplicated wholestage on 1101 1125 16 19.1 52.5 2.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Join w 2 ints: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Join w 2 ints wholestage off 193731 194139 577 0.1 9237.8 1.0X +Join w 2 ints wholestage on 192421 193110 576 0.1 9175.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Join w 2 longs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Join w 2 longs wholestage off 3577 3582 7 5.9 170.6 1.0X +Join w 2 longs wholestage on 2104 2112 6 10.0 100.3 1.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Join w 2 longs duplicated: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Join w 2 longs duplicated wholestage off 9580 9585 7 2.2 456.8 1.0X +Join w 2 longs duplicated wholestage on 6164 6189 32 3.4 293.9 1.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +outer join w long: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +outer join w long wholestage off 1662 1667 6 12.6 79.3 1.0X +outer join w long wholestage on 1061 1081 15 19.8 50.6 1.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +semi join w long: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +semi join w long wholestage off 1199 1204 7 17.5 57.2 1.0X +semi join w long wholestage on 678 692 12 30.9 32.3 1.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sort merge join: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +sort merge join wholestage off 554 566 17 3.8 264.3 1.0X +sort merge join wholestage on 467 489 18 4.5 222.8 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sort merge join with duplicates: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +sort merge join with duplicates wholestage off 1056 1059 4 2.0 503.7 1.0X +sort merge join with duplicates wholestage on 927 947 21 2.3 441.8 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +shuffle hash join: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +shuffle hash join wholestage off 526 538 17 8.0 125.4 1.0X +shuffle hash join wholestage on 411 430 16 10.2 98.0 1.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +broadcast nested loop join: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +broadcast nested loop join wholestage off 24826 24862 51 0.8 1183.8 1.0X +broadcast nested loop join wholestage on 18286 18488 194 1.1 872.0 1.4X + + diff --git a/sql/core/benchmarks/JsonBenchmark-jdk25-results.txt b/sql/core/benchmarks/JsonBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..a947a34a0ba89 --- /dev/null +++ b/sql/core/benchmarks/JsonBenchmark-jdk25-results.txt @@ -0,0 +1,130 @@ +================================================================================================ +Benchmark for performance of JSON parsing +================================================================================================ + +Preparing data for benchmarking ... +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +JSON schema inferring: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +No encoding 2323 2386 96 2.2 464.5 1.0X +UTF-8 is set 4970 4983 18 1.0 993.9 0.5X + +Preparing data for benchmarking ... +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +count a short column: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +No encoding 2147 2199 67 2.3 429.4 1.0X +UTF-8 is set 4826 4846 23 1.0 965.1 0.4X + +Preparing data for benchmarking ... +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +count a wide column: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +No encoding 4544 4564 22 0.2 4544.2 1.0X +UTF-8 is set 4411 4424 17 0.2 4411.0 1.0X + +Preparing data for benchmarking ... +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +select wide row: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +No encoding 9487 9565 91 0.0 189740.3 1.0X +UTF-8 is set 10224 10258 42 0.0 204476.7 0.9X + +Preparing data for benchmarking ... +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Select a subset of 10 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Select 10 columns 1678 1682 6 0.6 1677.6 1.0X +Select 1 column 1198 1200 3 0.8 1197.5 1.4X + +Preparing data for benchmarking ... +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +creation of JSON parser per line: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Short column without encoding 621 627 5 1.6 621.4 1.0X +Short column with UTF-8 1178 1184 11 0.8 1177.8 0.5X +Wide column without encoding 4988 5023 31 0.2 4987.6 0.1X +Wide column with UTF-8 6444 6510 61 0.2 6443.6 0.1X + +Preparing data for benchmarking ... +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +JSON functions: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Text read 50 51 2 19.9 50.2 1.0X +from_json 1046 1048 2 1.0 1045.9 0.0X +json_tuple 931 958 23 1.1 931.4 0.1X +get_json_object wholestage off 998 1001 3 1.0 998.2 0.1X +get_json_object wholestage on 913 915 4 1.1 912.5 0.1X + +Preparing data for benchmarking ... +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Dataset of json strings: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Text read 210 211 1 23.8 42.0 1.0X +schema inferring 1780 1785 7 2.8 356.0 0.1X +parsing 2586 2592 9 1.9 517.3 0.1X + +Preparing data for benchmarking ... +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Json files in the per-line mode: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Text read 574 577 4 8.7 114.8 1.0X +Schema inferring 2344 2347 2 2.1 468.9 0.2X +Parsing without charset 2927 2935 7 1.7 585.3 0.2X +Parsing with UTF-8 5678 5682 4 0.9 1135.5 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write dates and timestamps: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Create a dataset of timestamps 99 103 4 10.1 99.0 1.0X +to_json(timestamp) 533 535 3 1.9 532.7 0.2X +write timestamps to files 589 594 4 1.7 589.2 0.2X +Create a dataset of dates 105 107 2 9.5 104.8 0.9X +to_json(date) 398 402 3 2.5 398.3 0.2X +write dates to files 398 407 12 2.5 397.8 0.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read dates and timestamps: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------------------------- +read timestamp text from files 143 144 2 7.0 142.6 1.0X +read timestamps from files 1006 1009 3 1.0 1005.7 0.1X +infer timestamps from files 1849 1849 0 0.5 1849.1 0.1X +read date text from files 140 140 0 7.1 140.0 1.0X +read date from files 681 684 5 1.5 680.5 0.2X +timestamp strings 132 134 2 7.6 131.8 1.1X +parse timestamps from Dataset[String] 1134 1136 2 0.9 1134.1 0.1X +infer timestamps from Dataset[String] 1935 1938 3 0.5 1934.7 0.1X +date strings 194 198 4 5.1 194.3 0.7X +parse dates from Dataset[String] 935 936 1 1.1 935.1 0.2X +from_json(timestamp) 1563 1569 6 0.6 1562.8 0.1X +from_json(date) 1372 1398 35 0.7 1371.8 0.1X +infer error timestamps from Dataset[String] with default format 1335 1338 3 0.7 1335.2 0.1X +infer error timestamps from Dataset[String] with user-provided format 1318 1332 16 0.8 1317.6 0.1X +infer error timestamps from Dataset[String] with legacy format 1354 1356 1 0.7 1354.1 0.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Filters pushdown: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +w/o filters 5454 5462 11 0.0 54538.3 1.0X +pushdown disabled 5418 5427 11 0.0 54175.8 1.0X +w/ filters 584 591 6 0.2 5838.7 9.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Partial JSON results: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +parse invalid JSON 2244 2247 4 0.0 224391.1 1.0X + + diff --git a/sql/core/benchmarks/LargeRowBenchmark-jdk25-results.txt b/sql/core/benchmarks/LargeRowBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..ca9734c800df5 --- /dev/null +++ b/sql/core/benchmarks/LargeRowBenchmark-jdk25-results.txt @@ -0,0 +1,26 @@ +================================================================================================ +Large Row Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +#rows: 100, #cols: 10, cell: 1.3 MB: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +built-in UPPER 5829 5910 114 0.0 58291962.5 1.0X +udf UPPER 4106 4114 11 0.0 41057593.7 1.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +#rows: 1, #cols: 1, cell: 300.0 MB: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +built-in UPPER 1300 1307 10 0.0 1300108651.0 1.0X +udf UPPER 921 933 11 0.0 920948800.0 1.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +#rows: 1, #cols: 200, cell: 1.0 MB: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +built-in UPPER 1062 1081 27 0.0 1061725817.0 1.0X +udf UPPER 1271 1300 41 0.0 1271003935.0 0.8X + + diff --git a/sql/core/benchmarks/MakeDateTimeBenchmark-jdk25-results.txt b/sql/core/benchmarks/MakeDateTimeBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..5bdd4a86409c5 --- /dev/null +++ b/sql/core/benchmarks/MakeDateTimeBenchmark-jdk25-results.txt @@ -0,0 +1,22 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +make_date(): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +prepare make_date() 2190 2218 31 45.7 21.9 1.0X +make_date(2019, 9, 16) 1835 1843 8 54.5 18.4 1.2X +make_date(*, *, *) 3819 3820 1 26.2 38.2 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +make_timestamp(): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +prepare make_timestamp() 301 310 10 3.3 301.0 1.0X +make_timestamp(2019, 1, 2, 3, 4, 50.123456) 31 32 1 32.4 30.9 9.8X +make_timestamp(2019, 1, 2, 3, 4, 60.000000) 30 32 2 33.8 29.6 10.2X +make_timestamp(2019, 12, 31, 23, 59, 60.00) 28 28 0 36.1 27.7 10.9X +make_timestamp(*, *, *, 3, 4, 50.123456) 164 170 6 6.1 164.0 1.8X +make_timestamp(*, *, *, *, *, 0) 95 98 5 10.6 94.5 3.2X +make_timestamp(*, *, *, *, *, 60.0) 155 156 1 6.5 154.6 1.9X +make_timestamp(2019, 1, 2, *, *, *) 441 442 2 2.3 440.6 0.7X +make_timestamp(*, *, *, *, *, *) 475 477 2 2.1 474.7 0.6X + diff --git a/sql/core/benchmarks/MetadataStructBenchmark-jdk25-results.txt b/sql/core/benchmarks/MetadataStructBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..68cf3f9d233d2 --- /dev/null +++ b/sql/core/benchmarks/MetadataStructBenchmark-jdk25-results.txt @@ -0,0 +1,46 @@ +================================================================================================ +Metadata Struct Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Vectorized Parquet: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +no metadata columns 624 647 8 8.0 124.7 1.0X +_metadata.file_path 700 739 14 7.1 140.1 0.9X +_metadata.file_name 702 732 10 7.1 140.5 0.9X +_metadata.file_size 614 632 23 8.1 122.8 1.0X +_metadata.file_block_start 613 628 15 8.2 122.7 1.0X +_metadata.file_block_length 611 624 11 8.2 122.1 1.0X +_metadata.file_modification_time 610 625 11 8.2 122.1 1.0X +_metadata.row_index 687 714 9 7.3 137.4 0.9X +_metadata 982 1010 15 5.1 196.5 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Parquet-mr: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +no metadata columns 2753 2784 27 1.8 550.6 1.0X +_metadata.file_path 3347 3396 35 1.5 669.4 0.8X +_metadata.file_name 3352 3390 33 1.5 670.4 0.8X +_metadata.file_size 3201 3239 30 1.6 640.2 0.9X +_metadata.file_block_start 3205 3261 49 1.6 640.9 0.9X +_metadata.file_block_length 3200 3221 16 1.6 640.0 0.9X +_metadata.file_modification_time 3199 3235 37 1.6 639.7 0.9X +_metadata.row_index 3553 3596 31 1.4 710.7 0.8X +_metadata 4658 4684 21 1.1 931.6 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +JSON: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +no metadata columns 7155 7230 24 0.7 1431.1 1.0X +_metadata.file_path 8170 8229 20 0.6 1634.1 0.9X +_metadata.file_name 8114 8190 71 0.6 1622.8 0.9X +_metadata.file_size 7936 7974 34 0.6 1587.2 0.9X +_metadata.file_block_start 7910 7983 58 0.6 1582.0 0.9X +_metadata.file_block_length 7908 7943 22 0.6 1581.6 0.9X +_metadata.file_modification_time 7900 7941 32 0.6 1580.1 0.9X +_metadata 8766 8800 23 0.6 1753.1 0.8X + + diff --git a/sql/core/benchmarks/MetricsAggregationBenchmark-jdk25-results.txt b/sql/core/benchmarks/MetricsAggregationBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..a8ddceea2f815 --- /dev/null +++ b/sql/core/benchmarks/MetricsAggregationBenchmark-jdk25-results.txt @@ -0,0 +1,12 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +metrics aggregation (50 metrics, 100000 tasks per stage): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +---------------------------------------------------------------------------------------------------------------------------------------- +1 stage(s) 794 842 60 0.0 794149801.0 1.0X +2 stage(s) 1644 1666 32 0.0 1643656953.0 0.5X +3 stage(s) 2451 2503 73 0.0 2450888381.0 0.3X + +Stage Count Stage Proc. Time Aggreg. Time + 1 383 72 + 2 414 199 + 3 404 308 diff --git a/sql/core/benchmarks/MiscBenchmark-jdk25-results.txt b/sql/core/benchmarks/MiscBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..6f544213319cb --- /dev/null +++ b/sql/core/benchmarks/MiscBenchmark-jdk25-results.txt @@ -0,0 +1,127 @@ +================================================================================================ +filter & aggregate without group +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +range/filter/sum: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +range/filter/sum wholestage off 38848 39602 1065 54.0 18.5 1.0X +range/filter/sum wholestage on 2905 3484 325 722.0 1.4 13.4X + + +================================================================================================ +range/limit/sum +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +range/limit/sum: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +range/limit/sum wholestage off 65 72 11 8123.8 0.1 1.0X +range/limit/sum wholestage on 72 82 10 7295.6 0.1 0.9X + + +================================================================================================ +sample +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sample with replacement: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +sample with replacement wholestage off 8133 8151 26 16.1 62.0 1.0X +sample with replacement wholestage on 5105 5131 34 25.7 38.9 1.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +sample without replacement: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +sample without replacement wholestage off 2691 2713 30 48.7 20.5 1.0X +sample without replacement wholestage on 668 679 12 196.1 5.1 4.0X + + +================================================================================================ +collect +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collect: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +collect 1 million 169 235 85 6.2 160.8 1.0X +collect 2 millions 361 441 65 2.9 344.7 0.5X +collect 4 millions 783 933 140 1.3 746.8 0.2X + + +================================================================================================ +collect limit +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +collect limit: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +collect limit 1 million 170 255 85 6.2 162.2 1.0X +collect limit 2 millions 412 488 57 2.5 393.1 0.4X + + +================================================================================================ +generate explode +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +generate explode array: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +generate explode array wholestage off 12155 12238 118 1.4 724.5 1.0X +generate explode array wholestage on 2932 3040 176 5.7 174.8 4.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +generate explode map: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +generate explode map wholestage off 24186 24485 423 0.7 1441.6 1.0X +generate explode map wholestage on 8923 8971 44 1.9 531.9 2.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +generate posexplode array: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +generate posexplode array wholestage off 12858 12944 122 1.3 766.4 1.0X +generate posexplode array wholestage on 2893 2933 45 5.8 172.4 4.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +generate inline array: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +generate inline array wholestage off 6730 6737 10 2.5 401.1 1.0X +generate inline array wholestage on 2331 2448 100 7.2 138.9 2.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +generate big struct array: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +generate big struct array wholestage off 196 207 16 0.3 3269.7 1.0X +generate big struct array wholestage on 147 171 21 0.4 2446.6 1.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +generate big nested struct array: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------- +generate big nested struct array wholestage off 18803 19048 346 0.0 313387.7 1.0X +generate big nested struct array wholestage on 152 159 7 0.4 2536.6 123.5X + + +================================================================================================ +generate regular generator +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +generate stack: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +generate stack wholestage off 14042 14049 10 1.2 837.0 1.0X +generate stack wholestage on 2954 2961 10 5.7 176.1 4.8X + + diff --git a/sql/core/benchmarks/OrcNestedSchemaPruningBenchmark-jdk25-results.txt b/sql/core/benchmarks/OrcNestedSchemaPruningBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..ed238133b420d --- /dev/null +++ b/sql/core/benchmarks/OrcNestedSchemaPruningBenchmark-jdk25-results.txt @@ -0,0 +1,53 @@ +================================================================================================ +Nested Schema Pruning Benchmark For ORC v1 +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Selection: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 49 58 7 20.5 48.8 1.0X +Nested column 52 59 7 19.3 51.7 0.9X +Nested column in array 148 153 5 6.8 147.9 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Limiting: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 253 276 21 4.0 253.1 1.0X +Nested column 254 269 10 3.9 254.0 1.0X +Nested column in array 569 596 26 1.8 569.4 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Repartitioning: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 226 237 9 4.4 225.8 1.0X +Nested column 231 241 7 4.3 231.5 1.0X +Nested column in array 538 546 9 1.9 538.1 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Repartitioning by exprs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 225 233 7 4.5 224.6 1.0X +Nested column 250 259 7 4.0 249.8 0.9X +Nested column in array 579 596 8 1.7 578.9 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Sample: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 67 79 9 14.9 67.1 1.0X +Nested column 67 83 9 14.8 67.5 1.0X +Nested column in array 199 237 23 5.0 198.7 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Sorting: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 314 326 16 3.2 313.7 1.0X +Nested column 375 389 21 2.7 374.7 0.8X +Nested column in array 854 873 18 1.2 853.5 0.4X + + diff --git a/sql/core/benchmarks/OrcV2NestedSchemaPruningBenchmark-jdk25-results.txt b/sql/core/benchmarks/OrcV2NestedSchemaPruningBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..f3c5d6a3f9bc6 --- /dev/null +++ b/sql/core/benchmarks/OrcV2NestedSchemaPruningBenchmark-jdk25-results.txt @@ -0,0 +1,53 @@ +================================================================================================ +Nested Schema Pruning Benchmark For ORC v2 +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Selection: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 58 70 11 17.3 57.9 1.0X +Nested column 57 64 7 17.6 56.7 1.0X +Nested column in array 165 179 7 6.0 165.3 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Limiting: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 262 275 10 3.8 261.5 1.0X +Nested column 257 270 11 3.9 257.5 1.0X +Nested column in array 613 632 19 1.6 613.2 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Repartitioning: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 231 243 10 4.3 231.0 1.0X +Nested column 238 247 8 4.2 237.5 1.0X +Nested column in array 560 571 11 1.8 560.4 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Repartitioning by exprs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 229 240 8 4.4 228.7 1.0X +Nested column 254 265 7 3.9 253.7 0.9X +Nested column in array 577 595 11 1.7 577.1 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Sample: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 67 78 10 14.8 67.4 1.0X +Nested column 69 84 10 14.5 68.9 1.0X +Nested column in array 217 231 10 4.6 216.7 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Sorting: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 316 332 22 3.2 315.6 1.0X +Nested column 379 391 16 2.6 379.5 0.8X +Nested column in array 858 882 20 1.2 858.1 0.4X + + diff --git a/sql/core/benchmarks/ParquetNestedPredicatePushDownBenchmark-jdk25-results.txt b/sql/core/benchmarks/ParquetNestedPredicatePushDownBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..a88d94df0dff9 --- /dev/null +++ b/sql/core/benchmarks/ParquetNestedPredicatePushDownBenchmark-jdk25-results.txt @@ -0,0 +1,21 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Can skip all row groups: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without nested predicate Pushdown 6396 6446 73 16.4 61.0 1.0X +With nested predicate Pushdown 52 66 9 2023.3 0.5 123.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Can skip some row groups: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without nested predicate Pushdown 7119 7173 33 14.7 67.9 1.0X +With nested predicate Pushdown 43 64 13 2435.3 0.4 165.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Can skip no row groups: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Without nested predicate Pushdown 13292 13316 22 7.9 126.8 1.0X +With nested predicate Pushdown 13315 13343 30 7.9 127.0 1.0X + diff --git a/sql/core/benchmarks/ParquetNestedSchemaPruningBenchmark-jdk25-results.txt b/sql/core/benchmarks/ParquetNestedSchemaPruningBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..a1188b6ef5e91 --- /dev/null +++ b/sql/core/benchmarks/ParquetNestedSchemaPruningBenchmark-jdk25-results.txt @@ -0,0 +1,53 @@ +================================================================================================ +Nested Schema Pruning Benchmark For Parquet +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Selection: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 67 85 15 15.0 66.7 1.0X +Nested column 69 79 12 14.6 68.6 1.0X +Nested column in array 237 250 11 4.2 237.2 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Limiting: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 264 288 24 3.8 263.5 1.0X +Nested column 264 276 5 3.8 264.3 1.0X +Nested column in array 654 676 18 1.5 654.0 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Repartitioning: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 240 249 16 4.2 240.3 1.0X +Nested column 244 248 3 4.1 243.9 1.0X +Nested column in array 619 626 7 1.6 619.4 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Repartitioning by exprs: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 237 242 4 4.2 237.4 1.0X +Nested column 277 288 7 3.6 276.8 0.9X +Nested column in array 675 678 3 1.5 675.0 0.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Sample: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 80 94 7 12.5 80.2 1.0X +Nested column 88 108 19 11.3 88.4 0.9X +Nested column in array 303 322 18 3.3 302.5 0.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Sorting: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Top-level column 327 339 23 3.1 327.3 1.0X +Nested column 394 398 4 2.5 393.7 0.8X +Nested column in array 954 976 23 1.0 953.7 0.3X + + diff --git a/sql/core/benchmarks/PrimitiveArrayBenchmark-jdk25-results.txt b/sql/core/benchmarks/PrimitiveArrayBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..a1256adf432e6 --- /dev/null +++ b/sql/core/benchmarks/PrimitiveArrayBenchmark-jdk25-results.txt @@ -0,0 +1,12 @@ +================================================================================================ +Write primitive arrays in dataset +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +Write an array in Dataset: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Int 173 186 9 48.4 20.6 1.0X +Double 306 322 18 27.4 36.5 0.6X + + diff --git a/sql/core/benchmarks/RangeBenchmark-jdk25-results.txt b/sql/core/benchmarks/RangeBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..0f8777336095e --- /dev/null +++ b/sql/core/benchmarks/RangeBenchmark-jdk25-results.txt @@ -0,0 +1,15 @@ +================================================================================================ +range +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +range: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +full scan 12807 13048 223 40.9 24.4 1.0X +limit after range 22 25 3 24086.1 0.0 588.4X +filter after range 1153 1160 8 454.9 2.2 11.1X +count after range 331 333 1 1581.7 0.6 38.6X +count after limit after range 35 36 1 15012.0 0.1 366.7X + + diff --git a/sql/core/benchmarks/RecursiveCTEBenchmark-jdk25-results.txt b/sql/core/benchmarks/RecursiveCTEBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..8cf3298bf4af2 --- /dev/null +++ b/sql/core/benchmarks/RecursiveCTEBenchmark-jdk25-results.txt @@ -0,0 +1,95 @@ +================================================================================================ +Recursive CTE with only LocalRelation +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +First 10 integers: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +First 10 integers using VALUES 60 71 10 0.0 6037065.9 1.0X +First 10 integers using SELECT 67 76 8 0.0 6689686.4 0.9X +First 10 integers using SELECT and LIMIT 56 64 7 0.0 5647866.5 1.1X +First 10 integers referencing external table in anchor 93 98 5 0.0 9312423.2 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +First 20 integers: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +First 20 integers using VALUES 61 68 6 0.0 3037865.3 1.0X +First 20 integers using SELECT 54 55 1 0.0 2707510.7 1.1X +First 20 integers using SELECT and LIMIT 51 61 9 0.0 2546229.6 1.2X +First 20 integers referencing external table in anchor 94 107 17 0.0 4704921.9 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +First 30 integers: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +First 30 integers using VALUES 63 72 9 0.0 2100321.8 1.0X +First 30 integers using SELECT 63 64 1 0.0 2108302.1 1.0X +First 30 integers using SELECT and LIMIT 79 82 5 0.0 2644929.5 0.8X +First 30 integers referencing external table in anchor 98 110 11 0.0 3255049.5 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +First 40 integers: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +First 40 integers using VALUES 72 77 5 0.0 1790911.2 1.0X +First 40 integers using SELECT 72 76 4 0.0 1790603.6 1.0X +First 40 integers using SELECT and LIMIT 65 66 2 0.0 1614415.6 1.1X +First 40 integers referencing external table in anchor 107 116 12 0.0 2673178.0 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +First 50 integers: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +First 50 integers using VALUES 77 84 7 0.0 1539337.1 1.0X +First 50 integers using SELECT 76 79 2 0.0 1529592.8 1.0X +First 50 integers using SELECT and LIMIT 70 77 8 0.0 1395833.4 1.1X +First 50 integers referencing external table in anchor 108 110 2 0.0 2167671.1 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +First 60 integers: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +First 60 integers using VALUES 89 96 6 0.0 1482998.3 1.0X +First 60 integers using SELECT 85 88 3 0.0 1411086.4 1.1X +First 60 integers using SELECT and LIMIT 79 87 6 0.0 1324087.5 1.1X +First 60 integers referencing external table in anchor 124 140 21 0.0 2070073.7 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +First 70 integers: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +First 70 integers using VALUES 96 104 7 0.0 1376836.7 1.0X +First 70 integers using SELECT 97 105 7 0.0 1381674.5 1.0X +First 70 integers using SELECT and LIMIT 92 97 6 0.0 1314452.1 1.0X +First 70 integers referencing external table in anchor 130 132 3 0.0 1850514.3 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +First 80 integers: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +First 80 integers using VALUES 108 114 5 0.0 1354567.3 1.0X +First 80 integers using SELECT 112 116 4 0.0 1396524.4 1.0X +First 80 integers using SELECT and LIMIT 101 107 5 0.0 1265300.3 1.1X +First 80 integers referencing external table in anchor 144 152 7 0.0 1801582.3 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +First 90 integers: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------- +First 90 integers using VALUES 119 125 5 0.0 1320259.5 1.0X +First 90 integers using SELECT 120 130 10 0.0 1331984.5 1.0X +First 90 integers using SELECT and LIMIT 109 115 5 0.0 1215655.3 1.1X +First 90 integers referencing external table in anchor 162 167 8 0.0 1798717.1 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +First 100 integers: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------- +First 100 integers using VALUES 131 139 9 0.0 1305114.2 1.0X +First 100 integers using SELECT 129 136 8 0.0 1286431.8 1.0X +First 100 integers using SELECT and LIMIT 119 121 5 0.0 1186046.1 1.1X +First 100 integers referencing external table in anchor 168 180 14 0.0 1684846.6 0.8X + + diff --git a/sql/core/benchmarks/SetOperationsBenchmark-jdk25-results.txt b/sql/core/benchmarks/SetOperationsBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..32b61d27b1dc2 --- /dev/null +++ b/sql/core/benchmarks/SetOperationsBenchmark-jdk25-results.txt @@ -0,0 +1,13 @@ +================================================================================================ +Set Operations Benchmark +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Parsing + Analysis: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +UNION ALL 123 137 11 0.1 8221.7 1.0X +EXCEPT ALL 97 100 3 0.2 6455.8 1.3X +INTERSECT ALL 97 102 5 0.2 6484.2 1.3X + + diff --git a/sql/core/benchmarks/SortBenchmark-jdk25-results.txt b/sql/core/benchmarks/SortBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..7d44a95eeac94 --- /dev/null +++ b/sql/core/benchmarks/SortBenchmark-jdk25-results.txt @@ -0,0 +1,16 @@ +================================================================================================ +radix sort +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +radix sort 25000000: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +reference TimSort key prefix array 8404 8472 97 3.0 336.1 1.0X +reference Arrays.sort 2174 2260 122 11.5 87.0 3.9X +radix sort one byte 81 87 5 309.3 3.2 104.0X +radix sort two bytes 149 156 6 168.1 5.9 56.5X +radix sort eight bytes 574 598 21 43.5 23.0 14.6X +radix sort key prefix array 621 631 9 40.3 24.8 13.5X + + diff --git a/sql/core/benchmarks/StateStoreBasicOperationsBenchmark-jdk25-results.txt b/sql/core/benchmarks/StateStoreBasicOperationsBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..4cc48772488fc --- /dev/null +++ b/sql/core/benchmarks/StateStoreBasicOperationsBenchmark-jdk25-results.txt @@ -0,0 +1,144 @@ +================================================================================================ +put rows +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +putting 10000 rows (10000 rows to overwrite - rate 100): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------------- +In-memory 10 12 1 1.0 1007.1 1.0X +RocksDB (trackTotalNumberOfRows: true) 44 46 1 0.2 4433.7 0.2X +RocksDB (trackTotalNumberOfRows: false) 17 18 1 0.6 1712.2 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +putting 10000 rows (5000 rows to overwrite - rate 50): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------- +In-memory 11 12 1 0.9 1053.4 1.0X +RocksDB (trackTotalNumberOfRows: true) 46 48 1 0.2 4647.3 0.2X +RocksDB (trackTotalNumberOfRows: false) 17 18 1 0.6 1722.0 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +putting 10000 rows (1000 rows to overwrite - rate 10): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------- +In-memory 11 12 1 0.9 1055.3 1.0X +RocksDB (trackTotalNumberOfRows: true) 47 48 1 0.2 4703.6 0.2X +RocksDB (trackTotalNumberOfRows: false) 17 18 1 0.6 1723.5 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +putting 10000 rows (0 rows to overwrite - rate 0): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------- +In-memory 11 12 1 0.9 1090.7 1.0X +RocksDB (trackTotalNumberOfRows: true) 46 48 1 0.2 4623.5 0.2X +RocksDB (trackTotalNumberOfRows: false) 17 18 1 0.6 1686.2 0.6X + + +================================================================================================ +merge rows +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +merging 10000 rows with 10 values per key (10000 rows to overwrite - rate 100): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------------------- +RocksDB (trackTotalNumberOfRows: true) 563 578 7 0.0 56330.0 1.0X +RocksDB (trackTotalNumberOfRows: false) 191 198 3 0.1 19085.8 3.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +merging 10000 rows with 10 values per key (5000 rows to overwrite - rate 50): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------------ +RocksDB (trackTotalNumberOfRows: true) 491 506 7 0.0 49129.4 1.0X +RocksDB (trackTotalNumberOfRows: false) 189 194 3 0.1 18878.6 2.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +merging 10000 rows with 10 values per key (1000 rows to overwrite - rate 10): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------------ +RocksDB (trackTotalNumberOfRows: true) 436 445 5 0.0 43595.1 1.0X +RocksDB (trackTotalNumberOfRows: false) 190 196 3 0.1 18980.9 2.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +merging 10000 rows with 10 values per key (0 rows to overwrite - rate 0): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------------- +RocksDB (trackTotalNumberOfRows: true) 421 431 4 0.0 42101.7 1.0X +RocksDB (trackTotalNumberOfRows: false) 190 194 2 0.1 18979.7 2.2X + + +================================================================================================ +delete rows +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +trying to delete 10000 rows from 10000 rows(10000 rows are non-existing - rate 100): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------------------- +In-memory 0 1 0 20.4 49.1 1.0X +RocksDB (trackTotalNumberOfRows: true) 46 47 2 0.2 4590.3 0.0X +RocksDB (trackTotalNumberOfRows: false) 17 17 0 0.6 1656.1 0.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +trying to delete 10000 rows from 10000 rows(5000 rows are non-existing - rate 50): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------------------------------------- +In-memory 8 9 0 1.2 819.1 1.0X +RocksDB (trackTotalNumberOfRows: true) 46 47 1 0.2 4609.9 0.2X +RocksDB (trackTotalNumberOfRows: false) 17 18 2 0.6 1696.3 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +trying to delete 10000 rows from 10000 rows(1000 rows are non-existing - rate 10): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------------------------------------- +In-memory 9 10 1 1.1 900.0 1.0X +RocksDB (trackTotalNumberOfRows: true) 45 47 1 0.2 4515.5 0.2X +RocksDB (trackTotalNumberOfRows: false) 17 18 0 0.6 1700.8 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +trying to delete 10000 rows from 10000 rows(0 rows are non-existing - rate 0): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------------- +In-memory 10 11 1 1.1 952.4 1.0X +RocksDB (trackTotalNumberOfRows: true) 46 47 1 0.2 4585.3 0.2X +RocksDB (trackTotalNumberOfRows: false) 18 18 1 0.6 1761.6 0.5X + + +================================================================================================ +evict rows +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +evicting 10000 rows (maxTimestampToEvictInMillis: 9999) from 10000 rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------- +In-memory 10 11 1 1.0 1002.4 1.0X +RocksDB (trackTotalNumberOfRows: true) 43 44 1 0.2 4283.2 0.2X +RocksDB (trackTotalNumberOfRows: false) 17 18 1 0.6 1719.0 0.6X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +evicting 5000 rows (maxTimestampToEvictInMillis: 4999) from 10000 rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------ +In-memory 9 10 1 1.2 862.9 1.0X +RocksDB (trackTotalNumberOfRows: true) 23 24 1 0.4 2295.3 0.4X +RocksDB (trackTotalNumberOfRows: false) 10 10 0 1.0 1008.8 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +evicting 1000 rows (maxTimestampToEvictInMillis: 999) from 10000 rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------------------------- +In-memory 8 9 1 1.2 801.3 1.0X +RocksDB (trackTotalNumberOfRows: true) 7 8 0 1.4 731.0 1.1X +RocksDB (trackTotalNumberOfRows: false) 5 5 0 2.1 472.5 1.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +evicting 0 rows (maxTimestampToEvictInMillis: -1) from 10000 rows: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------- +In-memory 0 1 0 24.4 41.0 1.0X +RocksDB (trackTotalNumberOfRows: true) 3 3 0 3.0 332.0 0.1X +RocksDB (trackTotalNumberOfRows: false) 3 3 0 3.0 331.6 0.1X + + diff --git a/sql/core/benchmarks/StringFunctionsBenchmark-jdk25-results.txt b/sql/core/benchmarks/StringFunctionsBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..0dcdf640ec8bb --- /dev/null +++ b/sql/core/benchmarks/StringFunctionsBenchmark-jdk25-results.txt @@ -0,0 +1,11 @@ +================================================================================================ +SQL string functions +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +regexp_replace: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +regexp_replace('*-*', '(\\d+)', 'num') 380 392 11 2.6 379.6 1.0X + + diff --git a/sql/core/benchmarks/SubExprEliminationBenchmark-jdk25-results.txt b/sql/core/benchmarks/SubExprEliminationBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..747c0258f73c8 --- /dev/null +++ b/sql/core/benchmarks/SubExprEliminationBenchmark-jdk25-results.txt @@ -0,0 +1,25 @@ +================================================================================================ +Benchmark for performance of subexpression elimination +================================================================================================ + +Preparing data for benchmarking ... +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +from_json as subExpr in Project: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +subExprElimination false, codegen: true 6038 6297 250 0.0 60377757.1 1.0X +subExprElimination false, codegen: false 6146 6381 249 0.0 61462816.5 1.0X +subExprElimination true, codegen: true 1143 1228 107 0.0 11425909.9 5.3X +subExprElimination true, codegen: false 1129 1185 88 0.0 11294766.9 5.3X + +Preparing data for benchmarking ... +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +from_json as subExpr in Filter: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +subExprElimination false, codegen: true 6255 6356 105 0.0 62546639.4 1.0X +subExprElimination false, codegen: false 6170 6350 250 0.0 61696907.3 1.0X +subExprElimination true, codegen: true 1529 1566 45 0.0 15287124.2 4.1X +subExprElimination true, codegen: false 1474 1512 36 0.0 14740028.2 4.2X + + diff --git a/sql/core/benchmarks/TPCDSQueryBenchmark-jdk25-results.txt b/sql/core/benchmarks/TPCDSQueryBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..11e141f016f35 --- /dev/null +++ b/sql/core/benchmarks/TPCDSQueryBenchmark-jdk25-results.txt @@ -0,0 +1,810 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q1 662 784 152 0.7 1433.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q2 788 868 92 2.8 353.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q3 235 259 21 12.6 79.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q4 4361 4641 395 1.2 836.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q5 952 1139 265 5.9 169.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q6 1229 1234 6 2.5 393.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q7 556 619 52 8.8 113.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q8 414 449 35 7.5 133.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q9 879 890 10 0.0 25120719.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q10 2185 2258 102 0.9 1055.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q11 1812 2018 291 2.1 480.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q12 169 190 27 4.8 208.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q13 754 812 61 6.5 153.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q14a 5756 5787 44 0.9 1122.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q14b 4132 4216 120 1.2 805.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q15 372 404 53 4.5 223.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q16 628 681 67 2.5 401.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q17 1425 1523 139 3.3 303.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q18 1159 1178 27 3.1 321.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q19 289 335 54 10.8 92.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q20 191 208 22 8.0 124.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q21 713 741 42 16.6 60.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q22 3254 3301 67 3.6 274.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q23a 5470 5729 366 1.0 1046.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q23b 5539 5809 382 0.9 1059.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q24a 225 266 33 14.8 67.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q24b 220 243 31 15.2 65.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q25 1382 1416 47 3.4 294.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q26 329 357 24 10.5 95.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q27 525 551 34 9.3 107.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q28 1225 1274 69 2.4 425.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q29 1371 1419 68 3.4 291.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q30 412 450 42 0.7 1397.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q31 789 928 223 4.7 212.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q32 208 230 29 7.4 135.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q33 383 414 41 13.5 74.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q34 381 405 42 8.0 124.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q35 1420 1460 56 1.5 685.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q36 520 553 34 5.7 174.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q37 853 879 31 15.6 64.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q38 681 718 45 7.7 130.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q39a 1583 1623 57 7.5 133.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q39b 1563 1570 10 7.6 132.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q40 325 362 57 5.2 194.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q41 131 146 17 0.1 7285.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q42 158 172 16 18.8 53.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q43 309 334 39 9.5 104.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q44 315 347 33 9.2 108.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q45 195 223 29 4.9 203.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q46 478 509 34 6.5 153.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q47 1501 1552 72 2.0 505.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q48 860 878 19 5.7 174.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q49 518 543 42 10.8 92.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q50 596 640 69 5.4 183.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q51 2853 2875 30 1.3 777.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q52 155 170 18 19.1 52.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q53 295 335 35 10.1 99.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q54 1392 1438 64 3.8 263.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q55 151 163 12 19.7 50.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q56 382 416 40 13.5 73.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q57 764 816 45 2.0 499.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q58 403 442 45 12.7 78.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q59 634 668 47 4.7 214.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q60 396 428 51 13.1 76.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q61 580 598 31 5.4 185.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q62 176 191 22 4.5 221.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q63 286 300 19 10.4 96.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q64 2250 2476 319 3.1 325.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q65 609 718 123 4.9 205.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q66 440 487 52 5.3 189.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q67 5342 5400 82 0.6 1798.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q68 469 501 43 6.6 150.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q69 1907 1917 14 1.1 920.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q70 564 598 48 5.2 191.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q71 358 382 35 14.6 68.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q72 108641 111915 4630 0.1 7078.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q73 327 353 31 9.3 107.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q74 1088 1339 355 3.5 288.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q75 1501 1667 234 3.8 266.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q76 292 315 40 17.6 57.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q77 439 633 186 12.8 78.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q78 2340 2358 25 2.4 416.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q79 415 450 36 7.4 135.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q80 1067 1101 49 5.3 189.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q81 314 366 36 1.2 855.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q82 1157 1161 5 12.7 78.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q83 226 261 34 2.6 380.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q84 694 706 21 3.4 293.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q85 2064 2100 51 1.4 728.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q86 188 203 18 4.3 231.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q87 673 706 37 7.7 129.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q88 1284 1437 217 2.3 431.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q89 316 350 58 9.4 106.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q90 122 143 20 6.6 150.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q91 336 364 33 6.8 146.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q92 134 153 23 6.1 164.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q93 437 482 47 7.3 137.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q94 336 363 30 2.5 399.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q95 5387 5539 215 0.2 6398.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q96 177 195 16 16.8 59.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q97 1137 1149 17 3.9 258.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q98 272 294 25 10.9 91.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q99 261 290 36 5.8 172.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q5a-v2.7 980 1110 184 5.7 174.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q6-v2.7 1065 1098 46 2.9 341.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q10a-v2.7 2112 2125 17 1.0 1020.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q11-v2.7 1764 1896 188 2.1 467.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q12-v2.7 133 148 17 6.1 163.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q14-v2.7 3972 4195 315 1.3 774.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q14a-v2.7 8217 8258 58 0.6 1601.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q18a-v2.7 2007 2179 243 1.8 557.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q20-v2.7 171 182 15 9.0 111.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q22-v2.7 12545 12594 69 0.9 1059.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q22a-v2.7 1918 1963 64 6.2 162.0 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q24-v2.7 207 254 44 16.1 62.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q27a-v2.7 1398 1552 218 3.5 285.8 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q34-v2.7 360 391 37 8.5 117.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q35-v2.7 1393 1418 36 1.5 672.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q35a-v2.7 1369 1413 62 1.5 661.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q36a-v2.7 499 505 9 5.9 168.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q47-v2.7 1510 1574 90 2.0 508.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q49-v2.7 500 520 32 11.2 89.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q51a-v2.7 14836 15122 405 0.2 4040.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q57-v2.7 773 819 60 2.0 505.2 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q64-v2.7 2251 2518 378 3.1 325.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q67a-v2.7 8356 8485 182 0.4 2812.7 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q70a-v2.7 642 688 71 4.6 217.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q72-v2.7 111246 113281 2878 0.1 7248.3 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q74-v2.7 1222 1265 61 3.1 323.9 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q75-v2.7 1443 1724 398 3.9 256.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q77a-v2.7 1069 1149 113 5.3 190.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q78-v2.7 2149 2390 341 2.6 382.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q80a-v2.7 1624 1699 106 3.5 287.6 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q86a-v2.7 232 261 34 3.5 286.1 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +TPCDS: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +q98-v2.7 280 300 24 10.6 94.4 1.0X + diff --git a/sql/core/benchmarks/TakeOrderedAndProjectBenchmark-jdk25-results.txt b/sql/core/benchmarks/TakeOrderedAndProjectBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..0a34cfdbf73f0 --- /dev/null +++ b/sql/core/benchmarks/TakeOrderedAndProjectBenchmark-jdk25-results.txt @@ -0,0 +1,12 @@ +================================================================================================ +TakeOrderedAndProject +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +TakeOrderedAndProject with SMJ: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------- +TakeOrderedAndProject with SMJ for doExecute 128 138 11 0.1 12792.5 1.0X +TakeOrderedAndProject with SMJ for executeCollect 55 58 5 0.2 5502.3 2.3X + + diff --git a/sql/core/benchmarks/TopKBenchmark-jdk25-results.txt b/sql/core/benchmarks/TopKBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..43aabe9afea8d --- /dev/null +++ b/sql/core/benchmarks/TopKBenchmark-jdk25-results.txt @@ -0,0 +1,22 @@ +================================================================================================ +Top-K Computation +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Benchmark Top-K: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------------------- +ROW_NUMBER (PARTITION: , WindowGroupLimit: false) 9396 9596 154 2.2 448.1 1.0X +ROW_NUMBER (PARTITION: , WindowGroupLimit: true) 1671 1837 126 12.5 79.7 5.6X +ROW_NUMBER (PARTITION: PARTITION BY b, WindowGroupLimit: false) 12041 12290 143 1.7 574.2 0.8X +ROW_NUMBER (PARTITION: PARTITION BY b, WindowGroupLimit: true) 4890 5062 106 4.3 233.2 1.9X +RANK (PARTITION: , WindowGroupLimit: false) 10182 10396 163 2.1 485.5 0.9X +RANK (PARTITION: , WindowGroupLimit: true) 1899 1932 22 11.0 90.5 4.9X +RANK (PARTITION: PARTITION BY b, WindowGroupLimit: false) 12703 12982 193 1.7 605.7 0.7X +RANK (PARTITION: PARTITION BY b, WindowGroupLimit: true) 4956 5146 113 4.2 236.3 1.9X +DENSE_RANK (PARTITION: , WindowGroupLimit: false) 10108 10245 170 2.1 482.0 0.9X +DENSE_RANK (PARTITION: , WindowGroupLimit: true) 1908 1927 19 11.0 91.0 4.9X +DENSE_RANK (PARTITION: PARTITION BY b, WindowGroupLimit: false) 12617 12796 123 1.7 601.6 0.7X +DENSE_RANK (PARTITION: PARTITION BY b, WindowGroupLimit: true) 4944 5124 98 4.2 235.7 1.9X + + diff --git a/sql/core/benchmarks/UDFBenchmark-jdk25-results.txt b/sql/core/benchmarks/UDFBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..1d64a523d96bc --- /dev/null +++ b/sql/core/benchmarks/UDFBenchmark-jdk25-results.txt @@ -0,0 +1,59 @@ +================================================================================================ +UDF with mixed input types +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +long/nullable int/string to string: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------- +long/nullable int/string to string wholestage off 41 42 1 2.4 408.7 1.0X +long/nullable int/string to string wholestage on 37 44 7 2.7 374.0 1.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +long/nullable int/string to option: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------------- +long/nullable int/string to option wholestage off 26 26 0 3.8 261.1 1.0X +long/nullable int/string to option wholestage on 27 32 6 3.7 273.5 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +long/nullable int/string to primitive: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------ +long/nullable int/string to primitive wholestage off 23 23 0 4.4 226.3 1.0X +long/nullable int/string to primitive wholestage on 27 28 1 3.7 268.0 0.8X + + +================================================================================================ +UDF with primitive types +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +long/nullable int to string: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +long/nullable int to string wholestage off 26 29 5 3.9 257.5 1.0X +long/nullable int to string wholestage on 27 30 4 3.7 269.4 1.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +long/nullable int to option: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------- +long/nullable int to option wholestage off 26 28 3 3.9 258.2 1.0X +long/nullable int to option wholestage on 21 21 1 4.8 206.9 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +long/nullable int to primitive: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------- +long/nullable int to primitive wholestage off 15 16 0 6.5 154.8 1.0X +long/nullable int to primitive wholestage on 18 18 0 5.6 180.1 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz +UDF identity overhead: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Baseline 11 15 4 8.8 114.0 1.0X +With identity UDF 15 16 1 6.8 146.8 0.8X + + diff --git a/sql/core/benchmarks/UnsafeArrayDataBenchmark-jdk25-results.txt b/sql/core/benchmarks/UnsafeArrayDataBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..b7b1937e60853 --- /dev/null +++ b/sql/core/benchmarks/UnsafeArrayDataBenchmark-jdk25-results.txt @@ -0,0 +1,33 @@ +================================================================================================ +Benchmark UnsafeArrayData +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Read UnsafeArrayData: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Int 74 74 0 2265.9 0.4 1.0X +Double 159 159 0 1055.3 0.9 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Write UnsafeArrayData: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Int 13 17 3 1564.4 0.6 1.0X +Double 29 34 4 720.7 1.4 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Get primitive array from UnsafeArrayData: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Int 20 23 2 3199.0 0.3 1.0X +Double 40 44 1 1567.4 0.6 0.5X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Create UnsafeArrayData from primitive array: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +--------------------------------------------------------------------------------------------------------------------------- +Int 20 22 1 3174.0 0.3 1.0X +Double 44 47 2 1420.6 0.7 0.4X + + diff --git a/sql/core/benchmarks/UpdateFieldsBenchmark-jdk25-results.txt b/sql/core/benchmarks/UpdateFieldsBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..d0e49cb15b434 --- /dev/null +++ b/sql/core/benchmarks/UpdateFieldsBenchmark-jdk25-results.txt @@ -0,0 +1,26 @@ +================================================================================================ +Add 2 columns and drop 2 columns at 3 different depths of nesting +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Add 2 columns and drop 2 columns at 3 different depths of nesting: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------- +To non-nullable StructTypes using performant method 3 4 2 0.0 Infinity 1.0X +To nullable StructTypes using performant method 2 2 1 0.0 Infinity 1.9X +To non-nullable StructTypes using non-performant method 35 38 4 0.0 Infinity 0.1X +To nullable StructTypes using non-performant method 682 710 30 0.0 Infinity 0.0X + + +================================================================================================ +Add 50 columns and drop 50 columns at 100 different depths of nesting +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 9V74 80-Core Processor +Add 50 columns and drop 50 columns at 100 different depths of nesting: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +----------------------------------------------------------------------------------------------------------------------------------------------------- +To non-nullable StructTypes using performant method 715 744 25 0.0 Infinity 1.0X +To nullable StructTypes using performant method 749 759 8 0.0 Infinity 1.0X + + diff --git a/sql/core/benchmarks/V2FunctionBenchmark-jdk25-results.txt b/sql/core/benchmarks/V2FunctionBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..81275ca120ad4 --- /dev/null +++ b/sql/core/benchmarks/V2FunctionBenchmark-jdk25-results.txt @@ -0,0 +1,44 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +scalar function (long + long) -> long, result_nullable = true codegen = true: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------------ +native_long_add 8285 9045 1146 60.4 16.6 1.0X +java_long_add_default 21723 21796 88 23.0 43.4 0.4X +java_long_add_magic 10348 10363 24 48.3 20.7 0.8X +java_long_add_static_magic 10131 10199 60 49.4 20.3 0.8X +scala_long_add_default 22045 22090 53 22.7 44.1 0.4X +scala_long_add_magic 10283 10383 122 48.6 20.6 0.8X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +scalar function (long + long) -> long, result_nullable = false codegen = true: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------------- +native_long_add 9587 9596 11 52.2 19.2 1.0X +java_long_add_default 21477 21514 42 23.3 43.0 0.4X +java_long_add_magic 10253 10334 73 48.8 20.5 0.9X +java_long_add_static_magic 9618 9645 36 52.0 19.2 1.0X +scala_long_add_default 21584 21662 68 23.2 43.2 0.4X +scala_long_add_magic 10239 10256 23 48.8 20.5 0.9X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +scalar function (long + long) -> long, result_nullable = true codegen = false: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------------------------------------- +native_long_add 24733 24894 141 20.2 49.5 1.0X +java_long_add_default 30820 31059 295 16.2 61.6 0.8X +java_long_add_magic 36904 37227 502 13.5 73.8 0.7X +java_long_add_static_magic 35924 36309 497 13.9 71.8 0.7X +scala_long_add_default 29138 29707 950 17.2 58.3 0.8X +scala_long_add_magic 36450 36487 51 13.7 72.9 0.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +scalar function (long + long) -> long, result_nullable = false codegen = false: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +-------------------------------------------------------------------------------------------------------------------------------------------------------------- +native_long_add 23613 23635 21 21.2 47.2 1.0X +java_long_add_default 27068 27153 102 18.5 54.1 0.9X +java_long_add_magic 34719 34733 21 14.4 69.4 0.7X +java_long_add_static_magic 33698 33715 16 14.8 67.4 0.7X +scala_long_add_default 27285 27344 89 18.3 54.6 0.9X +scala_long_add_magic 34666 34684 16 14.4 69.3 0.7X + diff --git a/sql/core/benchmarks/WideSchemaBenchmark-jdk25-results.txt b/sql/core/benchmarks/WideSchemaBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..1d40eef919ef6 --- /dev/null +++ b/sql/core/benchmarks/WideSchemaBenchmark-jdk25-results.txt @@ -0,0 +1,158 @@ +================================================================================================ +parsing large select expressions +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +parsing large select: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +1 select expressions 0 0 0 0.0 328009.0 1.0X +100 select expressions 3 3 0 0.0 2849054.0 0.1X +2500 select expressions 66 67 1 0.0 65594162.0 0.0X + + +================================================================================================ +optimize large select expressions +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +optimize large select: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +100 columns 3 3 1 0.0 2920507.0 1.0X +1000 columns 18 19 2 0.0 17921933.0 0.2X +10000 columns 176 191 18 0.0 176342402.0 0.0X + + +================================================================================================ +many column field read and write +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +many column field r/w: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +1 cols x 100000 rows (read in-mem) 14 19 5 7.4 135.1 1.0X +1 cols x 100000 rows (exec in-mem) 14 19 5 7.1 141.2 1.0X +1 cols x 100000 rows (read parquet) 26 32 8 3.8 264.4 0.5X +1 cols x 100000 rows (write parquet) 104 115 14 1.0 1036.2 0.1X +100 cols x 1000 rows (read in-mem) 11 16 4 9.0 111.0 1.2X +100 cols x 1000 rows (exec in-mem) 14 19 6 7.2 138.9 1.0X +100 cols x 1000 rows (read parquet) 23 27 6 4.4 225.8 0.6X +100 cols x 1000 rows (write parquet) 101 111 15 1.0 1013.7 0.1X +2500 cols x 40 rows (read in-mem) 50 57 9 2.0 501.8 0.3X +2500 cols x 40 rows (exec in-mem) 79 86 7 1.3 790.2 0.2X +2500 cols x 40 rows (read parquet) 239 261 17 0.4 2389.6 0.1X +2500 cols x 40 rows (write parquet) 141 167 25 0.7 1411.4 0.1X + + +================================================================================================ +wide shallowly nested struct field read and write +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +wide shallowly nested struct field r/w: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +1 wide x 100000 rows (read in-mem) 20 24 6 5.1 196.2 1.0X +1 wide x 100000 rows (exec in-mem) 21 24 6 4.8 210.3 0.9X +1 wide x 100000 rows (read parquet) 22 26 7 4.6 217.9 0.9X +1 wide x 100000 rows (write parquet) 108 117 7 0.9 1084.3 0.2X +100 wide x 1000 rows (read in-mem) 15 18 4 6.9 145.9 1.3X +100 wide x 1000 rows (exec in-mem) 16 19 6 6.4 157.1 1.2X +100 wide x 1000 rows (read parquet) 21 25 5 4.7 213.9 0.9X +100 wide x 1000 rows (write parquet) 104 113 13 1.0 1043.5 0.2X +2500 wide x 40 rows (read in-mem) 21 24 4 4.7 214.1 0.9X +2500 wide x 40 rows (exec in-mem) 26 29 5 3.8 262.5 0.7X +2500 wide x 40 rows (read parquet) 65 69 4 1.5 647.1 0.3X +2500 wide x 40 rows (write parquet) 110 120 8 0.9 1103.3 0.2X + + +================================================================================================ +deeply nested struct field read and write +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +deeply nested struct field r/w: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +1 deep x 100000 rows (read in-mem) 15 19 4 6.5 154.5 1.0X +1 deep x 100000 rows (exec in-mem) 18 22 5 5.6 178.8 0.9X +1 deep x 100000 rows (read parquet) 18 22 6 5.7 177.0 0.9X +1 deep x 100000 rows (write parquet) 104 108 3 1.0 1044.9 0.1X +100 deep x 1000 rows (read in-mem) 50 56 5 2.0 502.8 0.3X +100 deep x 1000 rows (exec in-mem) 486 493 7 0.2 4858.2 0.0X +100 deep x 1000 rows (read parquet) 492 505 25 0.2 4916.4 0.0X +100 deep x 1000 rows (write parquet) 139 147 7 0.7 1385.9 0.1X +250 deep x 400 rows (read in-mem) 231 238 7 0.4 2310.3 0.1X +250 deep x 400 rows (exec in-mem) 2947 2954 10 0.0 29467.9 0.0X +250 deep x 400 rows (read parquet) 2902 2908 9 0.0 29016.8 0.0X +250 deep x 400 rows (write parquet) 320 323 2 0.3 3198.0 0.0X + + +================================================================================================ +bushy struct field read and write +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +bushy struct field r/w: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +1 x 1 deep x 100000 rows (read in-mem) 14 16 4 7.4 135.3 1.0X +1 x 1 deep x 100000 rows (exec in-mem) 15 18 4 6.6 150.6 0.9X +1 x 1 deep x 100000 rows (read parquet) 17 20 5 5.8 172.6 0.8X +1 x 1 deep x 100000 rows (write parquet) 102 107 5 1.0 1021.1 0.1X +128 x 8 deep x 1000 rows (read in-mem) 13 15 4 7.4 134.9 1.0X +128 x 8 deep x 1000 rows (exec in-mem) 15 17 4 6.8 147.6 0.9X +128 x 8 deep x 1000 rows (read parquet) 21 24 5 4.8 207.4 0.7X +128 x 8 deep x 1000 rows (write parquet) 102 106 5 1.0 1020.8 0.1X +1024 x 11 deep x 100 rows (read in-mem) 18 21 5 5.5 180.3 0.8X +1024 x 11 deep x 100 rows (exec in-mem) 22 25 4 4.5 222.2 0.6X +1024 x 11 deep x 100 rows (read parquet) 36 39 5 2.8 357.3 0.4X +1024 x 11 deep x 100 rows (write parquet) 106 112 7 0.9 1059.5 0.1X + + +================================================================================================ +wide array field read and write +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +wide array field r/w: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +1 wide x 100000 rows (read in-mem) 15 18 5 6.8 146.3 1.0X +1 wide x 100000 rows (exec in-mem) 19 22 4 5.3 190.3 0.8X +1 wide x 100000 rows (read parquet) 17 20 5 5.7 174.0 0.8X +1 wide x 100000 rows (write parquet) 103 109 6 1.0 1026.9 0.1X +100 wide x 1000 rows (read in-mem) 11 13 4 9.1 109.9 1.3X +100 wide x 1000 rows (exec in-mem) 13 15 4 8.0 125.4 1.2X +100 wide x 1000 rows (read parquet) 17 19 5 6.0 165.8 0.9X +100 wide x 1000 rows (write parquet) 98 103 4 1.0 984.9 0.1X +2500 wide x 40 rows (read in-mem) 11 12 4 9.3 107.7 1.4X +2500 wide x 40 rows (exec in-mem) 12 14 4 8.2 122.0 1.2X +2500 wide x 40 rows (read parquet) 17 19 5 6.0 165.9 0.9X +2500 wide x 40 rows (write parquet) 99 104 6 1.0 989.9 0.1X + + +================================================================================================ +wide map field read and write +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +wide map field r/w: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +1 wide x 100000 rows (read in-mem) 13 15 3 7.7 129.9 1.0X +1 wide x 100000 rows (exec in-mem) 16 18 3 6.2 161.0 0.8X +1 wide x 100000 rows (read parquet) 21 24 5 4.8 209.4 0.6X +1 wide x 100000 rows (write parquet) 101 103 3 1.0 1006.8 0.1X +100 wide x 1000 rows (read in-mem) 7 8 2 14.0 71.4 1.8X +100 wide x 1000 rows (exec in-mem) 9 10 3 10.9 91.8 1.4X +100 wide x 1000 rows (read parquet) 18 21 4 5.5 180.6 0.7X +100 wide x 1000 rows (write parquet) 94 98 4 1.1 942.7 0.1X +2500 wide x 40 rows (read in-mem) 9 10 2 11.4 87.6 1.5X +2500 wide x 40 rows (exec in-mem) 11 12 2 9.3 107.2 1.2X +2500 wide x 40 rows (read parquet) 18 21 5 5.5 181.8 0.7X +2500 wide x 40 rows (write parquet) 96 99 2 1.0 961.6 0.1X + + diff --git a/sql/core/benchmarks/WideTableBenchmark-jdk25-results.txt b/sql/core/benchmarks/WideTableBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..95468288b3062 --- /dev/null +++ b/sql/core/benchmarks/WideTableBenchmark-jdk25-results.txt @@ -0,0 +1,17 @@ +================================================================================================ +projection on wide table +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +projection on wide table: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +split threshold 10 2600 2613 14 0.4 2479.4 1.0X +split threshold 100 2124 2137 11 0.5 2025.5 1.2X +split threshold 1024 1627 1640 9 0.6 1551.9 1.6X +split threshold 2048 1594 1601 8 0.7 1520.0 1.6X +split threshold 4096 1867 1873 5 0.6 1781.0 1.4X +split threshold 8192 2295 2399 87 0.5 2188.8 1.1X +split threshold 65536 21956 22120 123 0.0 20939.2 0.1X + + diff --git a/sql/hive/benchmarks/InsertIntoHiveTableBenchmark-jdk25-hive2.3-results.txt b/sql/hive/benchmarks/InsertIntoHiveTableBenchmark-jdk25-hive2.3-results.txt new file mode 100644 index 0000000000000..396e34b5ed5a9 --- /dev/null +++ b/sql/hive/benchmarks/InsertIntoHiveTableBenchmark-jdk25-hive2.3-results.txt @@ -0,0 +1,11 @@ +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +insert hive table benchmark: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +INSERT INTO DYNAMIC 3421 3719 421 0.0 334099.4 1.0X +INSERT INTO HYBRID 486 507 15 0.0 47504.1 7.0X +INSERT INTO STATIC 157 193 21 0.1 15358.9 21.8X +INSERT OVERWRITE DYNAMIC 3100 3191 129 0.0 302732.5 1.1X +INSERT OVERWRITE HYBRID 462 480 12 0.0 45080.1 7.4X +INSERT OVERWRITE STATIC 182 193 8 0.1 17743.8 18.8X + diff --git a/sql/hive/benchmarks/ObjectHashAggregateExecBenchmark-jdk25-results.txt b/sql/hive/benchmarks/ObjectHashAggregateExecBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..00f90430b095f --- /dev/null +++ b/sql/hive/benchmarks/ObjectHashAggregateExecBenchmark-jdk25-results.txt @@ -0,0 +1,45 @@ +================================================================================================ +Hive UDAF vs Spark AF +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +hive udaf vs spark af: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +hive udaf w/o group by 3267 3301 28 0.0 49847.8 1.0X +spark af w/o group by 21 27 6 3.2 313.3 159.1X +hive udaf w/ group by 1989 2030 33 0.0 30355.8 1.6X +spark af w/ group by w/o fallback 22 26 4 3.0 328.3 151.8X +spark af w/ group by w/ fallback 25 30 8 2.6 379.3 131.4X + + +================================================================================================ +ObjectHashAggregateExec vs SortAggregateExec - typed_count +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +object agg v.s. sort agg: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +sort agg w/ group by 22755 23275 736 4.6 217.0 1.0X +object agg w/ group by w/o fallback 6805 7355 252 15.4 64.9 3.3X +object agg w/ group by w/ fallback 14547 14676 97 7.2 138.7 1.6X +sort agg w/o group by 3885 3909 21 27.0 37.1 5.9X +object agg w/o group by w/o fallback 3619 3717 104 29.0 34.5 6.3X + + +================================================================================================ +ObjectHashAggregateExec vs SortAggregateExec - percentile_approx +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +object agg v.s. sort agg: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +sort agg w/ group by 390 414 13 5.4 186.1 1.0X +object agg w/ group by w/o fallback 312 321 5 6.7 149.0 1.2X +object agg w/ group by w/ fallback 453 475 13 4.6 216.0 0.9X +sort agg w/o group by 274 280 4 7.7 130.6 1.4X +object agg w/o group by w/o fallback 285 290 3 7.4 135.7 1.4X + + diff --git a/sql/hive/benchmarks/OrcReadBenchmark-jdk25-results.txt b/sql/hive/benchmarks/OrcReadBenchmark-jdk25-results.txt new file mode 100644 index 0000000000000..e1a356fb6cb78 --- /dev/null +++ b/sql/hive/benchmarks/OrcReadBenchmark-jdk25-results.txt @@ -0,0 +1,222 @@ +================================================================================================ +SQL Single Numeric Column Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +SQL Single TINYINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 613 720 160 25.6 39.0 1.0X +Native ORC MR 804 835 28 19.6 51.1 0.8X +Native ORC Vectorized 97 123 22 161.5 6.2 6.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +SQL Single SMALLINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 694 713 21 22.7 44.1 1.0X +Native ORC MR 750 777 31 21.0 47.7 0.9X +Native ORC Vectorized 87 108 19 181.6 5.5 8.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +SQL Single INT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 769 798 42 20.4 48.9 1.0X +Native ORC MR 783 800 15 20.1 49.8 1.0X +Native ORC Vectorized 107 128 26 146.7 6.8 7.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +SQL Single BIGINT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 755 782 37 20.8 48.0 1.0X +Native ORC MR 872 900 29 18.0 55.4 0.9X +Native ORC Vectorized 108 145 33 146.1 6.8 7.0X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +SQL Single FLOAT Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 880 892 11 17.9 55.9 1.0X +Native ORC MR 860 896 49 18.3 54.6 1.0X +Native ORC Vectorized 145 159 22 108.2 9.2 6.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +SQL Single DOUBLE Column Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 896 930 45 17.6 57.0 1.0X +Native ORC MR 1070 1073 5 14.7 68.0 0.8X +Native ORC Vectorized 227 251 41 69.4 14.4 4.0X + + +================================================================================================ +Int and String Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Int and String Scan: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 1614 1621 10 6.5 153.9 1.0X +Native ORC MR 1557 1561 5 6.7 148.5 1.0X +Native ORC Vectorized 636 702 68 16.5 60.6 2.5X + + +================================================================================================ +Partitioned Table Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Partitioned Table: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Data column - Hive built-in ORC 837 886 53 18.8 53.2 1.0X +Data column - Native ORC MR 1037 1146 154 15.2 65.9 0.8X +Data column - Native ORC Vectorized 109 148 32 144.1 6.9 7.7X +Partition column - Hive built-in ORC 646 671 29 24.3 41.1 1.3X +Partition column - Native ORC MR 611 666 43 25.7 38.8 1.4X +Partition column - Native ORC Vectorized 42 57 17 372.8 2.7 19.8X +Both columns - Hive built-in ORC 964 1023 84 16.3 61.3 0.9X +Both columns - Native ORC MR 1117 1127 15 14.1 71.0 0.7X +Both columns - Native ORC Vectorized 113 154 38 139.5 7.2 7.4X + + +================================================================================================ +Repeated String Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Repeated String: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 888 914 23 11.8 84.7 1.0X +Native ORC MR 853 879 30 12.3 81.4 1.0X +Native ORC Vectorized 125 139 24 83.9 11.9 7.1X + + +================================================================================================ +String with Nulls Scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +String with Nulls Scan (0.0%): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 1437 1450 19 7.3 137.0 1.0X +Native ORC MR 1282 1291 13 8.2 122.3 1.1X +Native ORC Vectorized 283 290 8 37.0 27.0 5.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +String with Nulls Scan (50.0%): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 1436 1452 23 7.3 137.0 1.0X +Native ORC MR 1137 1155 26 9.2 108.4 1.3X +Native ORC Vectorized 326 359 43 32.2 31.1 4.4X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +String with Nulls Scan (95.0%): Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 730 804 119 14.4 69.6 1.0X +Native ORC MR 733 747 16 14.3 69.9 1.0X +Native ORC Vectorized 140 158 28 74.9 13.4 5.2X + + +================================================================================================ +Single Column Scan From Wide Columns +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Single Column Scan from 100 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 530 561 28 2.0 505.6 1.0X +Native ORC MR 94 109 18 11.2 89.2 5.7X +Native ORC Vectorized 36 42 7 29.1 34.4 14.7X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Single Column Scan from 200 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 961 979 20 1.1 916.1 1.0X +Native ORC MR 100 120 12 10.5 95.5 9.6X +Native ORC Vectorized 41 49 7 25.5 39.3 23.3X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Single Column Scan from 300 columns: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 1420 1442 32 0.7 1354.1 1.0X +Native ORC MR 107 113 5 9.8 101.6 13.3X +Native ORC Vectorized 50 62 9 21.1 47.3 28.6X + + +================================================================================================ +Struct scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Single Struct Column Scan with 10 Fields: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 321 382 59 3.3 306.3 1.0X +Native ORC MR 220 266 54 4.8 209.8 1.5X +Native ORC Vectorized 105 155 27 10.0 100.1 3.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Single Struct Column Scan with 100 Fields: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Hive built-in ORC 2095 2099 5 0.5 1998.0 1.0X +Native ORC MR 1740 1754 19 0.6 1659.9 1.2X +Native ORC Vectorized 1009 1038 41 1.0 962.1 2.1X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Single Struct Column Scan with 300 Fields: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Hive built-in ORC 6023 6085 87 0.2 5744.3 1.0X +Native ORC MR 5247 5279 46 0.2 5003.7 1.1X +Native ORC Vectorized 5216 5272 79 0.2 4974.4 1.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Single Struct Column Scan with 600 Fields: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------- +Hive built-in ORC 12954 13055 142 0.1 12354.3 1.0X +Native ORC MR 12160 12271 156 0.1 11596.8 1.1X +Native ORC Vectorized 12302 12424 173 0.1 11731.8 1.1X + + +================================================================================================ +Nested Struct scan +================================================================================================ + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Nested Struct Scan with 10 Elements, 10 Fields: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 2388 2397 13 0.4 2277.1 1.0X +Native ORC MR 1901 1924 33 0.6 1812.9 1.3X +Native ORC Vectorized 569 580 8 1.8 542.5 4.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Nested Struct Scan with 30 Elements, 10 Fields: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 6006 6303 419 0.2 5728.2 1.0X +Native ORC MR 4375 4378 5 0.2 4172.0 1.4X +Native ORC Vectorized 1447 1494 67 0.7 1379.7 4.2X + +OpenJDK 64-Bit Server VM 25.0.2+10-LTS on Linux 6.14.0-1017-azure +AMD EPYC 7763 64-Core Processor +Nested Struct Scan with 10 Elements, 30 Fields: Best Time(ms) Avg Time(ms) Stdev(ms) Rate(M/s) Per Row(ns) Relative +------------------------------------------------------------------------------------------------------------------------------ +Hive built-in ORC 5677 5694 25 0.2 5413.8 1.0X +Native ORC MR 5474 5488 19 0.2 5220.7 1.0X +Native ORC Vectorized 2000 2098 138 0.5 1907.5 2.8X + + From a0a092f9a9938d4e98d6adb5ab501475823f5e57 Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Fri, 27 Feb 2026 08:55:17 -0800 Subject: [PATCH 087/130] [SPARK-55746][SQL][TESTS] Fix unable to load custom metric object SupportedV1WriteMetric ### What changes were proposed in this pull request? Bug was introduced by SPARK-50315 (https://github.com/apache/spark/pull/48867), won't fail the test, just causes lots of warning logs ``` $ build/sbt "sql/testOnly *V1WriteFallbackSuite" ... 18:06:25.108 WARN org.apache.spark.sql.execution.ui.SQLAppStatusListener: Unable to load custom metric object for class `org.apache.spark.sql.connector.SupportedV1WriteMetric`. Please make sure that the custom metric class is in the classpath and it has 0-arg constructor. org.apache.spark.SparkException: org.apache.spark.sql.connector.SupportedV1WriteMetric did not have a zero-argument constructor or a single-argument constructor that accepts SparkConf. Note: if the class is defined inside of another Scala class, then its constructors may accept an implicit parameter that references the enclosing class; in this case, you must define the class as a top-level class in order to prevent this extra parameter from breaking Spark's ability to find a valid constructor. at org.apache.spark.util.Utils$.$anonfun$loadExtensions$1(Utils.scala:2871) at scala.collection.immutable.List.flatMap(List.scala:283) at scala.collection.immutable.List.flatMap(List.scala:79) at org.apache.spark.util.Utils$.loadExtensions(Utils.scala:2853) at org.apache.spark.sql.execution.ui.SQLAppStatusListener.$anonfun$aggregateMetrics$3(SQLAppStatusListener.scala:220) at scala.Option.map(Option.scala:242) at org.apache.spark.sql.execution.ui.SQLAppStatusListener.$anonfun$aggregateMetrics$2(SQLAppStatusListener.scala:214) ... (repeat many times) ``` ### Why are the changes needed? Fix UT. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Verified locally, no warnings printed after fixing. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54544 from pan3793/SPARK-55746. Authored-by: Cheng Pan Signed-off-by: Dongjoon Hyun --- .../apache/spark/sql/connector/V1WriteFallbackSuite.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/connector/V1WriteFallbackSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/connector/V1WriteFallbackSuite.scala index e396232eb70fe..d105b63dd78d8 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/connector/V1WriteFallbackSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/connector/V1WriteFallbackSuite.scala @@ -370,6 +370,10 @@ class InMemoryV1Provider } } +case class SupportedV1WriteMetric(name: String, description: String) extends CustomSumMetric { + def this() = this("dummy", "") +} + class InMemoryTableWithV1Fallback( override val name: String, override val schema: StructType, @@ -425,8 +429,6 @@ class InMemoryTableWithV1Fallback( } override def build(): V1Write = new V1Write { - case class SupportedV1WriteMetric(name: String, description: String) extends CustomSumMetric - override def supportedCustomMetrics(): Array[CustomMetric] = Array(SupportedV1WriteMetric("numOutputRows", "Number of output rows")) From eae6ede29253f4d71a16dd260a0b9d807652e468 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Fri, 27 Feb 2026 09:03:18 -0800 Subject: [PATCH 088/130] [SPARK-55741][INFRA] Use `ubuntu-slim` for GitHub Actions `precondition` and `ui` jobs ### What changes were proposed in this pull request? This PR aims to use `ubuntu-slim` for GitHub Actions `precondition` and `ui` job. ### Why are the changes needed? `ubuntu-slim` is a new cost-efficient runner to fit small jobs like `precondition`. We had better use this to save ASF infra usage (if possible) - https://github.blog/changelog/2025-10-28-1-vcpu-linux-runner-now-available-in-github-actions-in-public-preview/ - https://github.com/actions/runner-images/blob/main/images/ubuntu-slim/ubuntu-slim-Readme.md | Feature | `ubuntu-slim` | `ubuntu-latest` | | :--- | :---: | :---: | | **Cost (per minute)** | **$0.002** | **$0.012** | | **Cost for 1,000 mins** | **$2.00** | **$12.00** | | **CPU** | 1 vCPU | 4 vCPU | | **Memory (RAM)** | 5 GB | 16 GB | | **Storage (SSD)** | 14 GB | 14 GB | | **Maximum Runtime** | **15 Minutes** | 6 Hours | | **Isolation Type** | Container-based (L2) | Dedicated VM | ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Pass the CIs. Screenshot 2026-02-26 at 21 51 06 ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54537 from dongjoon-hyun/SPARK-55741. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- .github/workflows/build_and_test.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 12a2d78639cd9..bf3a58b233a86 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -59,7 +59,9 @@ concurrency: jobs: precondition: name: Check changes - runs-on: ubuntu-latest + # `ubuntu-slim` is lighter than `ubuntu-latest`. + # Please see https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#standard-github-hosted-runners-for-public-repositories + runs-on: ubuntu-slim env: GITHUB_PREV_SHA: ${{ github.event.before }} outputs: @@ -1480,7 +1482,9 @@ jobs: needs: [precondition] if: fromJson(needs.precondition.outputs.required).ui == 'true' name: Run Spark UI tests - runs-on: ubuntu-latest + # `ubuntu-slim` is lighter than `ubuntu-latest`. + # Please see https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#standard-github-hosted-runners-for-public-repositories + runs-on: ubuntu-slim timeout-minutes: 120 steps: - uses: actions/checkout@v6 From e2cd90bb3e1a17021a580ae6d755e9acad8afd62 Mon Sep 17 00:00:00 2001 From: Takuya Ueshin Date: Fri, 27 Feb 2026 11:47:32 -0800 Subject: [PATCH 089/130] [SPARK-55730][PYTHON] Not make timezone lower case ### What changes were proposed in this pull request? Not make timezone lower case. ### Why are the changes needed? The resolution of timezone has been changed in pandas 3: - https://pandas.pydata.org/pandas-docs/version/3.0/whatsnew/v3.0.0.html#pytz-now-an-optional-dependency which caused the issue that a lowercase timezone is not recognized by pandas' search in some environment. ``` ... File "/.../pandas/_libs/tslibs/timezones.pyx", line 133, in pandas._libs.tslibs.timezones.maybe_get_tz File "/.../pandas/_libs/tslibs/timezones.pyx", line 158, in pandas._libs.tslibs.timezones.maybe_get_tz File "/.../zoneinfo/_common.py", line 24, in load_tzdata raise ZoneInfoNotFoundError(f"No time zone found with key {key}") zoneinfo._common.ZoneInfoNotFoundError: 'No time zone found with key etc/utc' ``` If it's `Etc/UTC`, it works. ### Does this PR introduce _any_ user-facing change? Yes, it will behave more like pandas 3. ### How was this patch tested? Manually. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #54528 from ueshin/issues/SPARK-55730/timezone. Authored-by: Takuya Ueshin Signed-off-by: Takuya Ueshin --- python/pyspark/worker.py | 2 +- python/pyspark/worker_util.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/pyspark/worker.py b/python/pyspark/worker.py index a6ee3f25e4868..380cfb96db481 100644 --- a/python/pyspark/worker.py +++ b/python/pyspark/worker.py @@ -158,7 +158,7 @@ def int_to_decimal_coercion_enabled(self) -> bool: @property def timezone(self) -> Optional[str]: - return self.get("spark.sql.session.timeZone", None) + return self.get("spark.sql.session.timeZone", None, lower_str=False) @property def arrow_max_records_per_batch(self) -> int: diff --git a/python/pyspark/worker_util.py b/python/pyspark/worker_util.py index ccf937b5e734a..74835afa60dda 100644 --- a/python/pyspark/worker_util.py +++ b/python/pyspark/worker_util.py @@ -246,8 +246,8 @@ def load(self, infile: IO) -> None: v = utf8_deserializer.loads(infile) self._conf[k] = v - def get(self, key: str, default: Any = "") -> Any: + def get(self, key: str, default: Any = "", *, lower_str: bool = True) -> Any: val = self._conf.get(key, default) - if isinstance(val, str): + if isinstance(val, str) and lower_str: return val.lower() return val From 117e17114d516d54950d213298cb0b39bf0377a9 Mon Sep 17 00:00:00 2001 From: zeruibao Date: Fri, 27 Feb 2026 12:57:36 -0800 Subject: [PATCH 090/130] [SPARK-55510][SS] Fix deleteRange of Rocksdb state store to call changelogWriter ### What changes were proposed in this pull request? This PR adds changelog writer support for deleteRange in the RocksDB state store and exposes delete range operations through the State Data Source change feed via a new end_key column. Previously, deleteRange only performed the RocksDB native range deletion but did not record the operation in the changelog file. The changes include: #### Changelog write/replay support: - Added a new DELETE_RANGE_RECORD record type (byte 0x20) to the RecordType enum in StateStoreChangelog.scala - Added an abstract deleteRange(beginKey, endKey) method to StateStoreChangelogWriter, implemented in V2/V4 writers (V1/V3 throw UnsupportedOperationException, consistent with merge) - Updated StateStoreChangelogReaderV2 to parse DELETE_RANGE_RECORD entries - Updated RocksDB.deleteRange to write to the changelog after the native db.deleteRange call, with checksum encoding for endKey when rowChecksumEnabled is true - Updated RocksDB.replayChangelog to handle DELETE_RANGE_RECORD by verifying checksums and calling deleteRange during recovery #### State Data Source change feed integration: - Added a new end_key column (with key schema) to the State Data Source change feed output schema for all state variable types (generic, ValueState, ListState, MapState) - Updated the StateStoreChangeDataReader return type from a 4-tuple to a 5-tuple (RecordType, key, value, endKey, batchId) to carry the end key - Updated RocksDBStateStoreChangeDataReader.getNext() to decode both beginKey and endKey for DELETE_RANGE_RECORD, with proper column family prefix stripping and a .copy() on beginKey to avoid buffer reuse issues with RangeKeyScanStateEncoder - Updated HDFSBackedStateStoreChangeDataReader.getNext() to conform to the new 5-tuple (endKey is always null since HDFS does not support deleteRange) - Updated StateStoreChangeDataPartitionReader to map the new endKey field to the end_key schema column for both regular state types and MapState ### Why are the changes needed? When changelog checkpointing is enabled, the state store recovers by replaying changelog files rather than loading full snapshots. Since deleteRange was not recorded in the changelog, any range deletions were silently lost during changelog-based recovery, leading to data inconsistency -- keys that should have been deleted would reappear after a restart. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? UT ### Was this patch authored or co-authored using generative AI tooling? Yes, co-authored with Cursor Closes #54298 from zeruibao/zeruibao/SPARK-55510-fix-delete-range-to-call-changlog-writer. Authored-by: zeruibao Signed-off-by: Anish Shrigondekar --- .../execution/streaming/state/RocksDB.scala | 43 +++++++++-- .../state/RocksDBStateStoreProvider.scala | 5 ++ .../streaming/state/StateStore.scala | 1 - .../streaming/state/StateStoreChangelog.scala | 25 +++++++ .../state/RocksDBStateStoreSuite.scala | 74 ++++++++++++++++++- 5 files changed, 138 insertions(+), 10 deletions(-) diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/RocksDB.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/RocksDB.scala index 69a7e9618bb3d..a17c788d32079 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/RocksDB.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/RocksDB.scala @@ -981,6 +981,12 @@ class RocksDB( verifyChangelogRecord(kvVerifier, key, Some(value)) merge(key, value, includesPrefix = useColumnFamilies, deriveCfName = useColumnFamilies, includesChecksum = conf.rowChecksumEnabled) + + case RecordType.DELETE_RANGE_RECORD => + // For deleteRange, 'key' is beginKey and 'value' is endKey + verifyChangelogRecord(kvVerifier, key, Some(value)) + deleteRange(key, value, includesPrefix = useColumnFamilies, + includesChecksum = conf.rowChecksumEnabled) } } } finally { @@ -1438,29 +1444,50 @@ class RocksDB( * Delete all keys in the range [beginKey, endKey). * Uses RocksDB's native deleteRange for efficient bulk deletion. * - * @param beginKey The start key of the range (inclusive) - * @param endKey The end key of the range (exclusive) - * @param cfName The column family name + * @param beginKey The start key of the range (inclusive) + * @param endKey The end key of the range (exclusive) + * @param cfName The column family name + * @param includesPrefix Whether the keys already include the column family prefix. + * Set to true during changelog replay to avoid double-encoding. */ def deleteRange( beginKey: Array[Byte], endKey: Array[Byte], - cfName: String = StateStore.DEFAULT_COL_FAMILY_NAME): Unit = { + cfName: String = StateStore.DEFAULT_COL_FAMILY_NAME, + includesPrefix: Boolean = false, + includesChecksum: Boolean = false): Unit = { updateMemoryUsageIfNeeded() - val beginKeyWithPrefix = if (useColumnFamilies) { + val originalEndKey = if (conf.rowChecksumEnabled && includesChecksum) { + KeyValueChecksumEncoder.decodeAndVerifyValueRowWithChecksum( + readVerifier, beginKey, endKey, delimiterSize) + } else { + endKey + } + + val beginKeyWithPrefix = if (useColumnFamilies && !includesPrefix) { encodeStateRowWithPrefix(beginKey, cfName) } else { beginKey } - val endKeyWithPrefix = if (useColumnFamilies) { - encodeStateRowWithPrefix(endKey, cfName) + val endKeyWithPrefix = if (useColumnFamilies && !includesPrefix) { + encodeStateRowWithPrefix(originalEndKey, cfName) } else { - endKey + originalEndKey } db.deleteRange(writeOptions, beginKeyWithPrefix, endKeyWithPrefix) + changelogWriter.foreach { writer => + val endKeyForChangelog = if (conf.rowChecksumEnabled) { + KeyValueChecksumEncoder.encodeValueRowWithChecksum(endKeyWithPrefix, + KeyValueChecksum.create(beginKeyWithPrefix, Some(endKeyWithPrefix))) + } else { + endKeyWithPrefix + } + writer.deleteRange(beginKeyWithPrefix, endKeyForChangelog) + } + // TODO: Add metrics update for deleteRange operations } /** diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/RocksDBStateStoreProvider.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/RocksDBStateStoreProvider.scala index d8e0440e210d6..1dbf948e04345 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/RocksDBStateStoreProvider.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/RocksDBStateStoreProvider.scala @@ -1495,6 +1495,11 @@ class RocksDBStateStoreChangeDataReader( } val nextRecord = reader.next() + if (nextRecord._1 == RecordType.DELETE_RANGE_RECORD) { + throw new UnsupportedOperationException( + "DELETE_RANGE_RECORD is not supported in the state data source change feed. " + + "Range deletions cannot be expanded into individual key-value change records.") + } val keyBytes = if (storeConf.rowChecksumEnabled && nextRecord._1 == RecordType.DELETE_RECORD) { // remove checksum and decode to the original key diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStore.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStore.scala index e2d7c166a6755..12881ce368067 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStore.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStore.scala @@ -287,7 +287,6 @@ trait StateStore extends ReadStateStore { * Delete all keys in the range [beginKey, endKey). * Uses RocksDB's native deleteRange for efficient bulk deletion. * - * @note This operation is NOT recorded in the changelog. * @param beginKey The start key of the range (inclusive) * @param endKey The end key of the range (exclusive) * @param colFamilyName The column family name diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStoreChangelog.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStoreChangelog.scala index 2029c09887563..3c611e7a0de49 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStoreChangelog.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStoreChangelog.scala @@ -46,6 +46,7 @@ object RecordType extends Enumeration { val PUT_RECORD = Value("put_record") val DELETE_RECORD = Value("delete_record") val MERGE_RECORD = Value("merge_record") + val DELETE_RANGE_RECORD = Value("delete_range_record") // Generate byte representation of each record type def getRecordTypeAsByte(recordType: RecordType): Byte = { @@ -54,6 +55,7 @@ object RecordType extends Enumeration { case PUT_RECORD => 0x01.toByte case DELETE_RECORD => 0x10.toByte case MERGE_RECORD => 0x11.toByte + case DELETE_RANGE_RECORD => 0x20.toByte } } @@ -62,6 +64,7 @@ object RecordType extends Enumeration { case PUT_RECORD => "update" case DELETE_RECORD => "delete" case MERGE_RECORD => "append" + case DELETE_RANGE_RECORD => "delete_range" case _ => throw StateStoreErrors.unsupportedOperationException( "getRecordTypeAsString", recordType.toString) } @@ -74,6 +77,7 @@ object RecordType extends Enumeration { case 0x01 => PUT_RECORD case 0x10 => DELETE_RECORD case 0x11 => MERGE_RECORD + case 0x20 => DELETE_RANGE_RECORD case _ => throw new RuntimeException(s"Found invalid record type for value=$byte") } } @@ -128,6 +132,8 @@ abstract class StateStoreChangelogWriter( def merge(key: Array[Byte], value: Array[Byte]): Unit + def deleteRange(beginKey: Array[Byte], endKey: Array[Byte]): Unit + def abort(): Unit = { try { if (backingFileStream != null) backingFileStream.cancel() @@ -189,6 +195,11 @@ class StateStoreChangelogWriterV1( "changelog writer v1") } + override def deleteRange(beginKey: Array[Byte], endKey: Array[Byte]): Unit = { + throw new UnsupportedOperationException("Operation not supported with state " + + "changelog writer v1") + } + override def commit(): Unit = { try { // -1 in the key length field mean EOF. @@ -244,6 +255,15 @@ class StateStoreChangelogWriterV2( writePutOrMergeRecord(key, value, RecordType.MERGE_RECORD) } + override def deleteRange(beginKey: Array[Byte], endKey: Array[Byte]): Unit = { + assert(compressedStream != null) + compressedStream.write(RecordType.getRecordTypeAsByte(RecordType.DELETE_RANGE_RECORD)) + compressedStream.writeInt(beginKey.length) + compressedStream.write(beginKey) + compressedStream.writeInt(endKey.length) + compressedStream.write(endKey) + } + private def writePutOrMergeRecord(key: Array[Byte], value: Array[Byte], recordType: RecordType): Unit = { @@ -557,6 +577,11 @@ class StateStoreChangelogReaderV2( val valueBuffer = parseBuffer(input) (RecordType.MERGE_RECORD, keyBuffer, valueBuffer) + case RecordType.DELETE_RANGE_RECORD => + val beginKeyBuffer = parseBuffer(input) + val endKeyBuffer = parseBuffer(input) + (RecordType.DELETE_RANGE_RECORD, beginKeyBuffer, endKeyBuffer) + case _ => throw new IOException("Failed to process unknown record type") } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/state/RocksDBStateStoreSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/state/RocksDBStateStoreSuite.scala index 3c200b860f528..b1e888c31e285 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/state/RocksDBStateStoreSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/state/RocksDBStateStoreSuite.scala @@ -2509,7 +2509,7 @@ class RocksDBStateStoreSuite extends StateStoreSuiteBase[RocksDBStateStoreProvid } } - test("deleteRange - bulk deletion of keys in range") { + testWithRocksDBStateStore("deleteRange - bulk deletion of keys in range") { tryWithProviderResource( newStoreProvider( keySchemaWithRangeScan, @@ -2547,6 +2547,78 @@ class RocksDBStateStoreSuite extends StateStoreSuiteBase[RocksDBStateStoreProvid } } + test("deleteRange - changelog checkpointing records and replays range deletions") { + // useColumnFamilies = true is required to get changelog writer V2 which supports + // DELETE_RANGE_RECORD. V1 (used when useColumnFamilies = false) does not support it. + withSQLConf( + RocksDBConf.ROCKSDB_SQL_CONF_NAME_PREFIX + ".changelogCheckpointing.enabled" -> "true", + SQLConf.STATE_STORE_MIN_DELTAS_FOR_SNAPSHOT.key -> "100") { + val storeId = StateStoreId(newDir(), Random.nextInt(), 0) + val keyEncoderSpec = RangeKeyScanStateEncoderSpec(keySchemaWithRangeScan, Seq(0)) + val cfName = "testColFamily" + + // Create provider and commit version 1 with some data and a deleteRange + tryWithProviderResource( + newStoreProvider(storeId, keyEncoderSpec, + keySchema = keySchemaWithRangeScan, + useColumnFamilies = true)) { provider => + val store = provider.getStore(0) + store.createColFamilyIfAbsent(cfName, + keySchemaWithRangeScan, valueSchema, + RangeKeyScanStateEncoderSpec(keySchemaWithRangeScan, Seq(0))) + + // Put keys: (1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e") + store.put(dataToKeyRowWithRangeScan(1L, "a"), dataToValueRow(10), cfName) + store.put(dataToKeyRowWithRangeScan(2L, "b"), dataToValueRow(20), cfName) + store.put(dataToKeyRowWithRangeScan(3L, "c"), dataToValueRow(30), cfName) + store.put(dataToKeyRowWithRangeScan(4L, "d"), dataToValueRow(40), cfName) + store.put(dataToKeyRowWithRangeScan(5L, "e"), dataToValueRow(50), cfName) + store.commit() + + // Version 2: deleteRange [2, 4) - should delete keys 2 and 3 + val store2 = provider.getStore(1) + store2.createColFamilyIfAbsent(cfName, + keySchemaWithRangeScan, valueSchema, + RangeKeyScanStateEncoderSpec(keySchemaWithRangeScan, Seq(0))) + val beginKey = dataToKeyRowWithRangeScan(2L, "") + val endKey = dataToKeyRowWithRangeScan(4L, "") + store2.deleteRange(beginKey, endKey, cfName) + store2.commit() + } + + // Reload from a fresh provider (same storeId) to force changelog replay + tryWithProviderResource( + newStoreProvider(storeId, keyEncoderSpec, + keySchema = keySchemaWithRangeScan, + useColumnFamilies = true)) { reloadedProvider => + val reloadedStore = reloadedProvider.getStore(2) + try { + reloadedStore.createColFamilyIfAbsent(cfName, + keySchemaWithRangeScan, valueSchema, + RangeKeyScanStateEncoderSpec(keySchemaWithRangeScan, Seq(0))) + val remainingKeys = reloadedStore.iterator(cfName).map { kv => + keyRowWithRangeScanToData(kv.key) + }.toSeq + + // Keys 1, 4, 5 should remain; keys 2, 3 should have been deleted via replay + assert(remainingKeys.length === 3) + assert(remainingKeys.map(_._1).toSet === Set(1L, 4L, 5L)) + } finally { + if (!reloadedStore.hasCommitted) reloadedStore.abort() + } + + // Verify that the change data reader throws on DELETE_RANGE_RECORD + val reader = reloadedProvider.asInstanceOf[SupportsFineGrainedReplay] + .getStateStoreChangeDataReader(2, 2, Some(cfName)) + val ex = intercept[UnsupportedOperationException] { + reader.next() + } + assert(ex.getMessage.contains("DELETE_RANGE_RECORD")) + reader.closeIfNeeded() + } + } + } + test("Rocks DB task completion listener does not double unlock acquireThread") { // This test verifies that a thread that locks then unlocks the db and then // fires a completion listener (Thread 1) does not unlock the lock validly From 835689e0c343dc13c715c1b25aa5e16c70e3aed7 Mon Sep 17 00:00:00 2001 From: Holden Karau Date: Fri, 27 Feb 2026 14:13:07 -0800 Subject: [PATCH 091/130] [SPARK-47672][SQL] Avoid double eval from filter pushDown w/ projection pushdown ### What changes were proposed in this pull request? Changes the filter pushDown optimizer to not push down past projections of the same element if we reasonable expect that computing that element is likely to be expensive. This is a slightly complex alternative to https://github.com/apache/spark/pull/45802 which also moves parts of projections down so that the filters can move further down. An expression can indicate if it is too expensive to be worth the potential savings of being double evaluated as a result of pushdown (by default we do this for all UDFs). ### Future Work / What else remains to do? Right now if a cond is expensive and it references something in the projection we don't push-down. We could probably do better and gate this on if the thing we are reference is expensive rather than the condition it's self. We could do this as a follow up item or as part of this PR. ### Why are the changes needed? Currently Spark may double compute expensive operations (like json parsing, UDF eval, etc.) as a result of filter pushdown past projections. ### Does this PR introduce _any_ user-facing change? SQL optimizer change may impact some user queries, results should be the same and hopefully a little faster. ### How was this patch tested? New tests were added to the FilterPushDownSuite, and the initial problem of double evaluation was confirmed with a github gist ### Was this patch authored or co-authored using generative AI tooling? Used claude to generate more test coverage. Closes #46143 from holdenk/SPARK-47672-avoid-double-eval-from-filter-pushdown-split-projection. Lead-authored-by: Holden Karau Co-authored-by: Holden Karau Co-authored-by: Holden Karau Co-authored-by: Claude Signed-off-by: Holden Karau --- .../catalyst/expressions/AliasHelper.scala | 26 +++++ .../expressions/CallMethodViaReflection.scala | 3 + .../sql/catalyst/expressions/Expression.scala | 9 ++ .../sql/catalyst/expressions/ScalaUDF.scala | 2 + .../expressions/collectionOperations.scala | 2 + .../expressions/regexpExpressions.scala | 25 ++++ .../sql/catalyst/optimizer/Optimizer.scala | 75 +++++++++++- .../apache/spark/sql/internal/SQLConf.scala | 10 ++ .../optimizer/FilterPushdownSuite.scala | 109 +++++++++++++++++- 9 files changed, 256 insertions(+), 5 deletions(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/AliasHelper.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/AliasHelper.scala index 34393aaca7c67..2340385dcdd66 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/AliasHelper.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/AliasHelper.scala @@ -65,6 +65,32 @@ trait AliasHelper { }) } + /** + * Replace all attributes, that reference an alias, with the aliased expression. + * Tracks which aliases were replaced and returns them. + */ + protected def replaceAliasWhileTracking( + expr: Expression, + aliasMap: AttributeMap[Alias]): (Expression, AttributeMap[Alias]) = { + // Use transformUp to prevent infinite recursion when the replacement expression + // redefines the same ExprId, + var replaced = AttributeMap.empty[Alias] + val newExpr = trimAliases(expr.transformUp { + case a: Attribute => + // If we replace an alias add it to replaced + val newElem = aliasMap.get(a) + newElem match { + case None => a + case Some(b) => + if (!replaced.contains(a)) { + replaced += (a, b) + } + b + } + }) + (newExpr, replaced) + } + /** * Replace all attributes, that reference an alias, with the aliased expression, * but keep the name of the outermost attribute. diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/CallMethodViaReflection.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/CallMethodViaReflection.scala index cf34ceefdfee9..94d9b305d3b0a 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/CallMethodViaReflection.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/CallMethodViaReflection.scala @@ -67,6 +67,9 @@ case class CallMethodViaReflection( with CodegenFallback with QueryErrorsBase { + // This could be pretty much anything. + override def expensive: Boolean = true + def this(children: Seq[Expression]) = this(children, true) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Expression.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Expression.scala index b61f7ee0ee160..834f3b0debd08 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Expression.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Expression.scala @@ -404,6 +404,15 @@ abstract class Expression extends TreeNode[Expression] { } else { "" } + + /** + * Mark if an expression is likely to be expensive. + * The current only consumer of this is the pushdown optimizer. + * By default an expression is expensive if any of it's children are expensive. + */ + def expensive: Boolean = hasExpensiveChild + + protected lazy val hasExpensiveChild: Boolean = children.exists(_.expensive) } object ExpressionPatternBitMask { diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/ScalaUDF.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/ScalaUDF.scala index bba3d4b1a806b..b4dd41092871b 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/ScalaUDF.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/ScalaUDF.scala @@ -1210,4 +1210,6 @@ case class ScalaUDF( override protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]): ScalaUDF = copy(children = newChildren) + + override def expensive: Boolean = true } diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/collectionOperations.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/collectionOperations.scala index 6dddd9e6646c3..dc3e6dcbd388c 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/collectionOperations.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/collectionOperations.scala @@ -2293,6 +2293,8 @@ case class ArrayJoin( override def dataType: DataType = array.dataType.asInstanceOf[ArrayType].elementType override def prettyName: String = "array_join" + + override def expensive: Boolean = true } /** diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/regexpExpressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/regexpExpressions.scala index c6e5c480f3c2c..5ad360a54e8d5 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/regexpExpressions.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/regexpExpressions.scala @@ -83,6 +83,31 @@ abstract class StringRegexExpression extends BinaryExpression matches(regex, input1.asInstanceOf[UTF8String].toString) } } + + override def expensive: Boolean = hasExpensiveChild || _expensiveRegex + + // Heuristic, not designed to be perfect. Look for things likely to have + // back tracking. + private val detectExpensiveRegexPattern = Pattern.compile("\\+\\*\\{") + + private lazy val _expensiveRegex = { + // A quick heuristic for expensive a pattern is. + left match { + case StringLiteral(str) => + // If we have a clear start limited back tracking required. + if (str.startsWith("^") || str.startsWith("\\b")) { + false + } else if (detectExpensiveRegexPattern.matcher(str).matches()) { + // Greedy matching can be tricky. + true + } else { + // Default to pushdown for now. + false + } + case _ => + true // per row regex compilation. + } + } } private[catalyst] object StringRegexExpression { diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/Optimizer.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/Optimizer.scala index 712d02ac8eca8..c953258cff2f1 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/Optimizer.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/Optimizer.scala @@ -2059,23 +2059,92 @@ object PushDownPredicates extends Rule[LogicalPlan] { * Pushes [[Filter]] operators through many operators iff: * 1) the operator is deterministic * 2) the predicate is deterministic and the operator will not change any of rows. + * 3) We don't add double evaluation OR double evaluation would be cheap OR we're configured to. * - * This heuristic is valid assuming the expression evaluation cost is minimal. */ object PushPredicateThroughNonJoin extends Rule[LogicalPlan] with PredicateHelper { def apply(plan: LogicalPlan): LogicalPlan = plan transform applyLocally val applyLocally: PartialFunction[LogicalPlan, LogicalPlan] = { + // Projections are a special case because the filter _may_ contain references to fields added in + // the projection that we wish to copy. We shouldn't blindly copy everything + // since double evaluation all operations can be expensive (unless the broken behavior is + // enabled by the user). The double filter eval regression was added in Spark 3 fixed in 4.2. + // The _new_ default algorithm works as follows: + // Provided filters are broken up based on their &&s for separate evaluation. + // We track which components of the projection are used in the filters. + // + // 1) The filter does not reference anything in the projection: pushed + // 2) Filter which reference _inexpensive_ items in projection: pushed and reference resolved + // resulting in double evaluation, but only of inexpensive items -- worth it to filter + // records sooner. + // (Case 1 & 2 are treated as "cheap" predicates) + // 3) When an a filter references expensive to compute references we do not push it. + // Note that a given filter may contain parts (sepereated by logical ands) from all cases. + // We handle each part separately according to the logic above. + // Additional restriction: // SPARK-13473: We can't push the predicate down when the underlying projection output non- // deterministic field(s). Non-deterministic expressions are essentially stateful. This // implies that, for a given input row, the output are determined by the expression's initial // state and all the input rows processed before. In another word, the order of input rows // matters for non-deterministic expressions, while pushing down predicates changes the order. // This also applies to Aggregate. - case Filter(condition, project @ Project(fields, grandChild)) + case f @ Filter(condition, project @ Project(fields, grandChild)) if fields.forall(_.deterministic) && canPushThroughCondition(grandChild, condition) => + // All of the aliases in the projection val aliasMap = getAliasMap(project) - project.copy(child = Filter(replaceAlias(condition, aliasMap), grandChild)) + if (!SQLConf.get.avoidDoubleFilterEval) { + // If the user is ok with double evaluation of projections short circuit + project.copy(child = Filter(replaceAlias(condition, aliasMap), grandChild)) + } else { + // Break up the filter into its respective components by &&s. + val splitCondition = splitConjunctivePredicates(condition) + // Find the different aliases each component of the filter uses. + val originalAndRewrittenConditionsWithUsedAlias = splitCondition.map { cond => + // Here we get which aliases were used in a given filter so we can see if the filter + // referenced an expensive alias v.s. just checking if the filter is expensive. + val (replaced, usedAliases) = replaceAliasWhileTracking(cond, aliasMap) + (cond, usedAliases, replaced) + } + // Split the filter's components into cheap and expensive while keeping track of + // what each references from the projection. + val (cheapWithUsed, expensiveWithUsed) = originalAndRewrittenConditionsWithUsedAlias + .partition { case (cond, used, replaced) => + // Didn't use anything? We're good + if (used.isEmpty) { + true + } else if (!used.exists(_._2.child.expensive)) { + // If it's cheap we can push it because it might eliminate more data quickly and + // it may also be something which could be evaluated at the storage layer. + // We may wish to improve this heuristic in the future. + true + } else { + false + } + } + // Short circuit if we do not have any cheap filters return the original filter as is. + if (cheapWithUsed.isEmpty) { + f + } else { + val cheap: Seq[Expression] = cheapWithUsed.map(_._3) + // Make a base instance which has all of the cheap filters pushed down. + // For all filter which do not reference any expensive aliases then + // just push the filter while resolving the non-expensive aliases. + val combinedCheapFilter = cheap.reduce(And) + val baseChild = Filter(combinedCheapFilter, child = grandChild) + // Take our projection and place it on top of the pushed filters. + val topProjection = project.copy(child = baseChild) + + // If we pushed all the filters we can return the projection + if (expensiveWithUsed.isEmpty) { + topProjection + } else { + // Finally add any filters which could not be pushed + val remainingConditions = expensiveWithUsed.map(_._1) + Filter(remainingConditions.reduce(And), topProjection) + } + } + } // We can push down deterministic predicate through Aggregate, including throwable predicate. // If we can push down a filter through Aggregate, it means the filter only references the diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala index 1874ff195516b..1d59c7a087869 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala @@ -482,6 +482,14 @@ object SQLConf { .booleanConf .createWithDefault(true) + val AVOID_DOUBLE_FILTER_EVAL = + buildConf("spark.sql.optimizer.avoidDoubleFilterEval") + .doc("When true avoid pushing expensive (UDF, etc.) filters down if it could result in" + + "double evaluation. This was the behaviour prior to 3.X.") + .version("4.2.0") + .booleanConf + .createWithDefault(true) + val OPTIMIZER_EXCLUDED_RULES = buildConf("spark.sql.optimizer.excludedRules") .doc("Configures a list of rules to be disabled in the optimizer, in which the rules are " + "specified by their rule names and separated by comma. It is not guaranteed that all the " + @@ -8015,6 +8023,8 @@ class SQLConf extends Serializable with Logging with SqlApiConf { def preserveCharVarcharTypeInfo: Boolean = getConf(SQLConf.PRESERVE_CHAR_VARCHAR_TYPE_INFO) + def avoidDoubleFilterEval: Boolean = getConf(AVOID_DOUBLE_FILTER_EVAL) + def readSideCharPadding: Boolean = getConf(SQLConf.READ_SIDE_CHAR_PADDING) def cliPrintHeader: Boolean = getConf(SQLConf.CLI_PRINT_HEADER) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/FilterPushdownSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/FilterPushdownSuite.scala index 9424ecda0ed8b..f457eced4d985 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/FilterPushdownSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/FilterPushdownSuite.scala @@ -27,6 +27,7 @@ import org.apache.spark.sql.catalyst.expressions._ import org.apache.spark.sql.catalyst.plans._ import org.apache.spark.sql.catalyst.plans.logical._ import org.apache.spark.sql.catalyst.rules._ +import org.apache.spark.sql.internal.SQLConf import org.apache.spark.sql.types._ import org.apache.spark.unsafe.types.CalendarInterval @@ -52,11 +53,14 @@ class FilterPushdownSuite extends PlanTest { val attrB = $"b".int val attrC = $"c".int val attrD = $"d".int + val attrE = $"e".string val testRelation = LocalRelation(attrA, attrB, attrC) val testRelation1 = LocalRelation(attrD) + val testStringRelation = LocalRelation(attrA, attrB, attrE) + val simpleDisjunctivePredicate = ("x.a".attr > 3) && ("y.a".attr > 13) || ("x.a".attr > 1) && ("y.a".attr > 11) val expectedPredicatePushDownResult = { @@ -152,7 +156,7 @@ class FilterPushdownSuite extends PlanTest { test("can't push without rewrite") { val originalQuery = testRelation - .select($"a" + $"b" as "e") + .select($"a" + $"b" as "e", $"a" - $"b" as "f") .where($"e" === 1) .analyze @@ -160,9 +164,110 @@ class FilterPushdownSuite extends PlanTest { val correctAnswer = testRelation .where($"a" + $"b" === 1) - .select($"a" + $"b" as "e") + .select($"a" + $"b" as "e", $"a" - $"b" as "f") + .analyze + + comparePlans(optimized, correctAnswer) + } + + test("SPARK-47672: Do double evaluation when configured") { + withSQLConf(SQLConf.AVOID_DOUBLE_FILTER_EVAL.key -> "false") { + val originalQuery = testStringRelation + .select($"a", $"e".rlike("magic") as "f", $"e".rlike("notmagic") as "j", $"b") + .where($"a" > 5 && $"f") + .analyze + + val optimized = Optimize.execute(originalQuery) + + val correctAnswer = testStringRelation + .where($"a" > 5 && $"e".rlike("magic")) + .select($"a", $"e".rlike("magic") as "f", $"e".rlike("notmagic") as "j", $"b") .analyze + comparePlans(optimized, correctAnswer) + } + } + + test("SPARK-47672: Make sure that we handle the case where everything is expensive") { + val originalQuery = testStringRelation + .select($"e".rlike("magic") as "f") + .where($"f") + .analyze + + val optimized = Optimize.execute(originalQuery) + + // Nothing changes when everything is expensive. + val correctAnswer = originalQuery + + comparePlans(optimized, correctAnswer) + } + + // Case 1: Multiple filters that don't reference any projection aliases - all should be pushed + test("SPARK-47672: Case 1 - multiple filters not referencing projection aliases") { + val originalQuery = testStringRelation + .select($"a" as "c", $"e".rlike("magic") as "f", $"b" as "d", $"a", $"b") + .where($"a" > 5 && $"b" < 10) + .analyze + + val optimized = Optimize.execute(originalQuery) + + // Both filters on c and d should be pushed down since they just reference + // simple aliases (c->a, d->b) which are inexpensive + val correctAnswer = testStringRelation + .where($"a" > 5 && $"b" < 10) + .select($"a" as "c", $"e".rlike("magic") as "f", $"b" as "d", $"a", $"b") + .analyze + + comparePlans(optimized, correctAnswer) + } + + // Case 2: Multiple filters with inexpensive references - all should be pushed + test("SPARK-47672: Case 2 - multiple filters with inexpensive alias references") { + val originalQuery = testStringRelation + .select($"a" + $"b" as "sum", $"a" - $"b" as "diff", $"e".rlike("magic") as "f") + .where($"sum" > 10 && $"diff" < 5) + .analyze + + val optimized = Optimize.execute(originalQuery) + + // Both sum and diff are inexpensive (arithmetic), so both filters should be pushed + val correctAnswer = testStringRelation + .where($"a" + $"b" > 10 && $"a" - $"b" < 5) + .select($"a" + $"b" as "sum", $"a" - $"b" as "diff", $"e".rlike("magic") as "f") + .analyze + + comparePlans(optimized, correctAnswer) + } + + // Case 3: Filter references expensive to compute references. + test("SPARK-47672: Avoid double evaluation with projections can't push past certain items") { + val originalQuery = testStringRelation + .select($"a", $"e".rlike("magic") as "f") + .where($"a" > 5 || $"f") + .analyze + + val optimized = Optimize.execute(originalQuery) + + comparePlans(optimized, originalQuery) + } + + // Combined case 1, 2, and 3 filter pushdown + test("SPARK-47672: Case 1, 2, and 3 make sure we leave up and push down correctly.") { + val originalQuery = testStringRelation + .select($"a" + $"b" as "sum", $"a" - $"b" as "diff", $"e".rlike("magic") as "f") + .where($"sum" > 10 && $"diff" < 5 && $"f") + .analyze + + val optimized = Optimize.execute(originalQuery) + + // Both sum and diff are inexpensive (arithmetic), so both pushed + // rlike magic is expensive so not pushed. + val correctAnswer = testStringRelation + .where($"a" + $"b" > 10 && $"a" - $"b" < 5) + .select($"a" + $"b" as "sum", $"a" - $"b" as "diff", $"e".rlike("magic") as "f") + .where($"f") + .analyze + comparePlans(optimized, correctAnswer) } From 168e5cf57147eed3e789b6d609a60396750094e4 Mon Sep 17 00:00:00 2001 From: Celeste Horgan Date: Fri, 27 Feb 2026 14:16:51 -0800 Subject: [PATCH 092/130] [DOCS] Clarify DataFrames in quickstart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? This pull request clarifies some of the language around DataFrames and Datasets in the Python Quickstart, and corrects some grammar/sentence structure in the first section of the Quickstart guide. No breaking changes are introduced. ### Why are the changes needed? The Quickstart is one of the highest traffic-ed pages in any documentation website. The original authors saw fit to introduce the idea of DataFrames vs. Datasets in the Python quickstart, but the user needs to understand *why* that matters (namely, that other languages they might use Spark in implement things differently – indeed, the Scala quickstart one tab over sticks entirely with the concept of Datasets). ### Does this PR introduce _any_ user-facing change? Yes! Some language in https://spark.apache.org/docs/latest/quick-start.html changes. ### How was this patch tested? This patch was built locally to ensure the website still built. ### Was this patch authored or co-authored using generative AI tooling? No Closes #54428 from celestehorgan/update-quickstart. Authored-by: Celeste Horgan Signed-off-by: Holden Karau --- docs/quick-start.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/docs/quick-start.md b/docs/quick-start.md index 83fc3421c0381..f9fd4921a9baa 100644 --- a/docs/quick-start.md +++ b/docs/quick-start.md @@ -51,13 +51,19 @@ Or if PySpark is installed with pip in your current environment: pyspark -Spark's primary abstraction is a distributed collection of items called a Dataset. Datasets can be created from Hadoop InputFormats (such as HDFS files) or by transforming other Datasets. Due to Python's dynamic nature, we don't need the Dataset to be strongly-typed in Python. As a result, all Datasets in Python are Dataset[Row], and we call it `DataFrame` to be consistent with the data frame concept in Pandas and R. Let's make a new DataFrame from the text of the README file in the Spark source directory: +Spark's primary abstracted is called a **Dataset**. A Dataset is a structured set of information. You can create datasets from Hadoop InputFormats (such as HDFS +files) or by transforming other Datasets. + +Datasets behave differently in some languages. Because Python allows for dynamic typing, Datasets in Python are all `Dataset[Row]` on an implementation level. +This leads to another key Spark concept: a `DataFrame`, or a Dataset with named columns. If you're familiar with DataFrames from pandas or R, you'll be familiar with how DataFrames work in Spark. In other languages, like Java, the difference between a Dataset and DataFrame is larger, but for now let's proceed with Python. + +Let's make a new DataFrame using the `README.md` file in the Spark souce directory via the command line: {% highlight python %} >>> textFile = spark.read.text("README.md") {% endhighlight %} -You can get values from DataFrame directly, by calling some actions, or transform the DataFrame to get a new one. For more details, please read the _[API doc](api/python/index.html#pyspark.sql.DataFrame)_. +Once you've created the DataFrame, you can perform actions against it, or transform it into another DataFrame. For more details see the [API doc](api/python/index.html#pyspark.sql.DataFrame). {% highlight python %} >>> textFile.count() # Number of rows in this DataFrame @@ -67,13 +73,13 @@ You can get values from DataFrame directly, by calling some actions, or transfor Row(value=u'# Apache Spark') {% endhighlight %} -Now let's transform this DataFrame to a new one. We call `filter` to return a new DataFrame with a subset of the lines in the file. +Now let's transform this DataFrame to a new one. The `filter` function returns a new DataFrame with a subset of the lines in the file. {% highlight python %} >>> linesWithSpark = textFile.filter(textFile.value.contains("Spark")) {% endhighlight %} -We can chain together transformations and actions: +You can also chain together transformations and actions: {% highlight python %} >>> textFile.filter(textFile.value.contains("Spark")).count() # How many lines contain "Spark"? @@ -86,14 +92,17 @@ We can chain together transformations and actions: ./bin/spark-shell -Spark's primary abstraction is a distributed collection of items called a Dataset. Datasets can be created from Hadoop InputFormats (such as HDFS files) or by transforming other Datasets. Let's make a new Dataset from the text of the README file in the Spark source directory: +Spark's primary abstracted is called a **Dataset**. A Dataset is a structured set of information. You can create datasets from Hadoop InputFormats (such as HDFS +files) or by transforming other Datasets. + +Let's make a new DataFrame using the `README.md` file in the Spark souce directory via the command line: {% highlight scala %} scala> val textFile = spark.read.textFile("README.md") textFile: org.apache.spark.sql.Dataset[String] = [value: string] {% endhighlight %} -You can get values from Dataset directly, by calling some actions, or transform the Dataset to get a new one. For more details, please read the _[API doc](api/scala/org/apache/spark/sql/Dataset.html)_. +Once you've created the Dataset, you can perform actions and transformations against it. For more details, see the [API doc](api/scala/org/apache/spark/sql/Dataset.html). {% highlight scala %} scala> textFile.count() // Number of items in this Dataset @@ -103,7 +112,7 @@ scala> textFile.first() // First item in this Dataset res1: String = # Apache Spark {% endhighlight %} -Now let's transform this Dataset into a new one. We call `filter` to return a new Dataset with a subset of the items in the file. +Now let's transform this Dataset into a new one. The `filter` function returns a new Dataset with a subset of the items in the file. {% highlight scala %} scala> val linesWithSpark = textFile.filter(line => line.contains("Spark")) From f66c3361852214d2adc35ed1dc4a1980057dba6f Mon Sep 17 00:00:00 2001 From: Helios He Date: Sat, 28 Feb 2026 13:44:28 +0800 Subject: [PATCH 093/130] [SPARK-55501][SQL] Fix listagg distinct + within group order by bug ### What changes were proposed in this pull request? There is unexpected behaviour with listagg expression and using DISTINCT and ORDER BY together, when the ORDER BY column is non-string/binary. The ListAgg.child gets casted to a string type, and the CheckAnalyzer/Resolver evaluates the child column as not semantically equal to the ORDER BY column. This fails the query (since it believes the listagg.child column is not enough to determine order, and could produce non-deterministic results). This is not the expected behaviour, as the ORDER BY column is deterministic since it's equivalent to the child col (before casting). The fix I'm proposing is to loosen the restriction on the check by the Analyzer/Resolver. We allow the listagg query to execute with DISTINCT + ORDER BY as long as each child col (with GROUP BY equality) maps to 1 unique value in the order expression col (they do not have to be the same. e.g. we could have `child_col = order_col % 10`. This PR only implements the loosened restriction for the case where the child col is a cast of the order col, for which we need to also handle the reverse direction; we need to ensure that the child col without casting is semantically equal to the ORDER BY col and the cast is safe. We follow this criteria to determine if a DataType can be safely casted to StringType (no datatype is implicitly casted to BinaryType, so we can ignore): For 2 values a,b, of DataType T: 1. if GROUP BY a = b, then CAST(a) = CAST(b) 2. if GROUP BY a != b, then CAST(a) != CAST(b) We only consider the datatypes that can be casted to string (e.g. we ignore complex datatypes like Array, Struct, Map). The only 2 DataTypes that don't pass these criteria are DoubleType and FloatType, since GROUP BY 0.0 = -0.0, but CAST(a as STRING) = "0.0" != CAST(b as STRING) = "-0.0". This is because Double/Float are normalized before GROUP BY, but not before casting. Other numeric types are casted using `.toString()` or `toPlainString()` which preserve precision/scale. Datetime/Interval types are converted with no loss. ### Why are the changes needed? It's a bug, as explained above. ### Does this PR introduce _any_ user-facing change? Yes. Previous behaviour resulted in error: Example query: ``` SELECT listagg(distinct col, ', ') within group (order by col) FROM VALUES (3), (1), (100), (99), (1) t(col) ``` throws `[INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT] Invalid function `listagg` with WITHIN GROUP. The function is invoked with DISTINCT and WITHIN GROUP but expressions "col" and "col" do not match. The WITHIN GROUP ordering expression must be picked from the function inputs. SQLSTATE: 42K0K;` I'm proposing that this query (and similar ones) now pass with the result `1, 3, 99, 100`. We also throw a new error for when the child col is a cast on the order col and is invalid: `[INVALID_WITHIN_GROUP_EXPRESSION_MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST]` It is a user-facing change compared to the released Spark versions. ### How was this patch tested? Unit tests added to `DataFrameAggregateSuite`. ### Was this patch authored or co-authored using generative AI tooling? Co-authored. Generated-by: Claude v2.1.39 Closes #54297 from helioshe4/listagg-distinct-within-group-bug. Authored-by: Helios He Signed-off-by: Wenchen Fan --- .../resources/error/error-conditions.json | 5 + .../sql/catalyst/analysis/CheckAnalysis.scala | 5 +- .../AggregateExpressionResolver.scala | 18 +- .../expressions/aggregate/collect.scala | 157 +++++++++++++ .../sql/errors/QueryCompilationErrors.scala | 12 + .../apache/spark/sql/internal/SQLConf.scala | 13 ++ .../listagg-collations.sql.out | 69 ++++++ .../analyzer-results/listagg.sql.out | 207 +++++++++++++++++- .../sql-tests/inputs/listagg-collations.sql | 16 ++ .../resources/sql-tests/inputs/listagg.sql | 28 ++- .../results/listagg-collations.sql.out | 75 +++++++ .../sql-tests/results/listagg.sql.out | 201 ++++++++++++++++- .../spark/sql/DataFrameAggregateSuite.scala | 25 +++ 13 files changed, 801 insertions(+), 30 deletions(-) diff --git a/common/utils/src/main/resources/error/error-conditions.json b/common/utils/src/main/resources/error/error-conditions.json index 52a21e43ea9eb..b76e3b5c8d56e 100644 --- a/common/utils/src/main/resources/error/error-conditions.json +++ b/common/utils/src/main/resources/error/error-conditions.json @@ -4296,6 +4296,11 @@ "The function is invoked with DISTINCT and WITHIN GROUP but expressions and do not match. The WITHIN GROUP ordering expression must be picked from the function inputs." ] }, + "MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST" : { + "message" : [ + "The function with DISTINCT and WITHIN GROUP (ORDER BY) is not supported for input. Explicitly cast the input to before passing it to both the function argument and ORDER BY expression." + ] + }, "WITHIN_GROUP_MISSING" : { "message" : [ "WITHIN GROUP is required for the function." diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala index 7e134d7f23ebe..c03ffa1167164 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala @@ -449,9 +449,8 @@ trait CheckAnalysis extends LookupCatalog with QueryErrorsBase with PlanToString messageParameters = Map("funcName" -> toSQLExpr(w))) case agg @ AggregateExpression(listAgg: ListAgg, _, _, _, _) - if agg.isDistinct && listAgg.needSaveOrderValue => - throw QueryCompilationErrors.functionAndOrderExpressionMismatchError( - listAgg.prettyName, listAgg.child, listAgg.orderExpressions) + if agg.isDistinct && listAgg.hasDistinctOrderAmbiguity => + listAgg.throwDistinctOrderError() case w: WindowExpression => WindowResolution.validateResolvedWindowExpression(w) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/resolver/AggregateExpressionResolver.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/resolver/AggregateExpressionResolver.scala index b194a4e44a9d1..d98b699349c99 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/resolver/AggregateExpressionResolver.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/resolver/AggregateExpressionResolver.scala @@ -78,8 +78,10 @@ class AggregateExpressionResolver( * 2. Handle [[OuterReference]] in [[AggregateExpression]], if there are any (see * `handleOuterAggregateExpression`); * - Validation: - * 1. [[ListAgg]] is not allowed in DISTINCT aggregates if it contains [[SortOrder]] different - * from its child; + * 1. [[ListAgg]] is not allowed in DISTINCT aggregates if the order value is ambiguous + * after deduplication. When [[SQLConf.LISTAGG_ALLOW_DISTINCT_CAST_WITH_ORDER]] is + * enabled, a mismatch is tolerated if the child value uniquely determines the order + * value (see [[ListAgg.hasDistinctOrderAmbiguity]]); * 2. Nested aggregate functions are not allowed; * 3. Nondeterministic expressions in the subtree of a related aggregate function are not * allowed; @@ -116,8 +118,8 @@ class AggregateExpressionResolver( private def validateResolvedAggregateExpression(aggregateExpression: AggregateExpression): Unit = aggregateExpression match { case agg @ AggregateExpression(listAgg: ListAgg, _, _, _, _) - if agg.isDistinct && listAgg.needSaveOrderValue => - throwFunctionAndOrderExpressionMismatchError(listAgg) + if agg.isDistinct && listAgg.hasDistinctOrderAmbiguity => + listAgg.throwDistinctOrderError() case _ => if (expressionResolutionContextStack.peek().hasAggregateExpressions) { throwNestedAggregateFunction(aggregateExpression) @@ -212,14 +214,6 @@ class AggregateExpressionResolver( } } - private def throwFunctionAndOrderExpressionMismatchError(listAgg: ListAgg) = { - throw QueryCompilationErrors.functionAndOrderExpressionMismatchError( - listAgg.prettyName, - listAgg.child, - listAgg.orderExpressions - ) - } - private def throwNestedAggregateFunction(aggregateExpression: AggregateExpression): Nothing = { throw new AnalysisException( errorClass = "NESTED_AGGREGATE_FUNCTION", diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/aggregate/collect.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/aggregate/collect.scala index a864bf1084366..8f6b80ebbe772 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/aggregate/collect.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/aggregate/collect.scala @@ -21,6 +21,7 @@ import scala.collection.mutable import scala.collection.mutable.{ArrayBuffer, Growable} import scala.util.{Left, Right} +import org.apache.spark.SparkException import org.apache.spark.sql.catalyst.InternalRow import org.apache.spark.sql.catalyst.analysis.TypeCheckResult import org.apache.spark.sql.catalyst.analysis.TypeCheckResult.{DataTypeMismatch, TypeCheckSuccess} @@ -31,6 +32,7 @@ import org.apache.spark.sql.catalyst.util.{ArrayData, GenericArrayData, TypeUtil import org.apache.spark.sql.catalyst.util.TypeUtils.toSQLExpr import org.apache.spark.sql.errors.{QueryCompilationErrors, QueryErrorsBase} import org.apache.spark.sql.errors.DataTypeErrors.{toSQLId, toSQLType} +import org.apache.spark.sql.internal.SQLConf import org.apache.spark.sql.internal.types.StringTypeWithCollation import org.apache.spark.sql.types._ import org.apache.spark.unsafe.types.{ByteArray, UTF8String} @@ -592,6 +594,161 @@ case class ListAgg( false } + /** + * Returns true if the order value may be ambiguous after DISTINCT deduplication. + * + * For LISTAGG(DISTINCT child) WITHIN GROUP (ORDER BY order_expr), correctness requires + * a functional dependency (child -> order_expr, where equality is defined by GROUP BY + * semantics): each distinct child value must map to exactly one order value. Otherwise, + * after deduplication on child, the order value is ambiguous. + * + * When child = Cast(order_expr, T) where T is STRING or BINARY (LISTAGG's accepted input + * types), the functional dependency (child -> order_expr) is satisfied since casting to + * string/binary is injective for the types we allow. However, the cast must also be + * equality-preserving (order_expr -> child): GROUP BY-equal order values must produce + * GROUP BY-equal child values. Otherwise, the DISTINCT rewrite (which groups by child) may + * split values that should be in the same group, causing over-counting. + * For example, Float/Double violate this because -0.0 and 0.0 are GROUP BY-equal but cast + * to different strings. This is checked by [[isCastEqualityPreserving]] and + * [[isCastTargetEqualityPreserving]]. + * + * Currently only detects these conditions for Cast. + * TODO(SPARK-55718): extend to detect other functional dependencies. + * + * Returns false when the order expression matches the child (i.e., [[needSaveOrderValue]] + * is false). Otherwise, the behavior depends on the + * [[SQLConf.LISTAGG_ALLOW_DISTINCT_CAST_WITH_ORDER]] config: + * - If enabled, delegates to [[checkOrderValueDeterminism]] to determine whether the + * order value is uniquely determined by the child. + * - If disabled, any mismatch is considered ambiguous. + * + * @return true if ambiguity exists, false if the order value is deterministic + * @see [[throwDistinctOrderError]] to throw the appropriate error when this returns true + */ + def hasDistinctOrderAmbiguity: Boolean = { + needSaveOrderValue && { + if (SQLConf.get.listaggAllowDistinctCastWithOrder) { + checkOrderValueDeterminism match { + case OrderDeterminismResult.Deterministic => false + case _ => true + } + } else { + true + } + } + } + + def throwDistinctOrderError(): Nothing = { + if (SQLConf.get.listaggAllowDistinctCastWithOrder) { + checkOrderValueDeterminism match { + case OrderDeterminismResult.NonDeterministicMismatch => + throwFunctionAndOrderExpressionMismatchError() + case OrderDeterminismResult.NonDeterministicCast(inputType, castType) => + throwFunctionAndOrderExpressionUnsafeCastError(inputType, castType) + case OrderDeterminismResult.Deterministic => + throw SparkException.internalError( + "ListAgg.throwDistinctOrderError should not be called when the cast is safe") + } + } else { + throwFunctionAndOrderExpressionMismatchError() + } + } + + private def throwFunctionAndOrderExpressionMismatchError() = { + throw QueryCompilationErrors.functionAndOrderExpressionMismatchError( + prettyName, child, orderExpressions) + } + + private def throwFunctionAndOrderExpressionUnsafeCastError( + inputType: DataType, castType: DataType) = { + throw QueryCompilationErrors.functionAndOrderExpressionUnsafeCastError( + prettyName, inputType, castType) + } + + /** + * Checks whether the order value is uniquely determined by the child value. + * + * Currently only handles the case where child = Cast(order_expr, T). If the cast is + * equality-preserving, the order value is deterministic (each child string maps back to + * exactly one original value). Otherwise, returns + * [[OrderDeterminismResult.NonDeterministicMismatch]]. + * + * @see [[hasDistinctOrderAmbiguity]] + */ + private def checkOrderValueDeterminism: OrderDeterminismResult = { + if (orderExpressions.size != 1) return OrderDeterminismResult.NonDeterministicMismatch + child match { + case Cast(castChild, castType, _, _) + if orderExpressions.head.child.semanticEquals(castChild) => + if (isCastEqualityPreserving(castChild.dataType) && + isCastTargetEqualityPreserving(castType)) { + OrderDeterminismResult.Deterministic + } else { + OrderDeterminismResult.NonDeterministicCast(castChild.dataType, castType) + } + case _ => OrderDeterminismResult.NonDeterministicMismatch + } + } + + /** + * Returns true if casting `dt` to string/binary preserves equality semantics: values that + * are GROUP BY-equal must cast to equal results, and different results must imply different + * original values. Types like Float/Double are unsafe because IEEE 754 negative zero (-0.0) + * and positive zero (0.0) are equal but produce different string representations. + * + * @see [[checkOrderValueDeterminism]] + */ + private def isCastEqualityPreserving(dt: DataType): Boolean = dt match { + case _: IntegerType | LongType | ShortType | ByteType => true + case _: DecimalType => true + case _: DateType | TimestampNTZType => true + case _: TimeType => true + case _: CalendarIntervalType => true + case _: YearMonthIntervalType => true + case _: DayTimeIntervalType => true + case BooleanType => true + case BinaryType => true + case st: StringType => st.isUTF8BinaryCollation + case _: DoubleType | FloatType => false + // During DST fall-back, two distinct UTC epochs can format to the same local time string + // because the default format omits the timezone offset. TimestampNTZType is safe (uses UTC). + case _: TimestampType => false + case _ => false + } + + /** + * Returns true if the cast target type preserves equality semantics for DISTINCT + * deduplication. A non-binary-equality collation on the target [[StringType]] can cause + * different source values to become equal after casting (e.g., "ABC" and "abc" are different + * under UTF8_BINARY but equal under UTF8_LCASE). + * + * @see [[checkOrderValueDeterminism]] + */ + private def isCastTargetEqualityPreserving(dt: DataType): Boolean = dt match { + case st: StringType => st.isUTF8BinaryCollation + case BinaryType => true + case _ => false + } + + /** + * Result of checking whether the order value is uniquely determined by the child value + * after DISTINCT deduplication. Currently only handles Cast. + */ + private sealed trait OrderDeterminismResult + + private object OrderDeterminismResult { + /** The order value is uniquely determined by the child value. */ + case object Deterministic extends OrderDeterminismResult + + /** Non-deterministic: cannot establish a child -> order functional dependency. */ + case object NonDeterministicMismatch extends OrderDeterminismResult + + /** Non-deterministic: the cast does not preserve equality semantics. */ + case class NonDeterministicCast( + inputType: DataType, + castType: DataType) extends OrderDeterminismResult + } + override protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]): Expression = copy( child = newChildren.head, diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala index a6174b82077b6..8cdd734def4aa 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala @@ -1116,6 +1116,18 @@ private[sql] object QueryCompilationErrors extends QueryErrorsBase with Compilat "orderingExpr" -> orderExpr.map(order => toSQLExpr(order.child)).mkString(", "))) } + def functionAndOrderExpressionUnsafeCastError( + functionName: String, + inputType: DataType, + castType: DataType): Throwable = { + new AnalysisException( + errorClass = "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + messageParameters = Map( + "funcName" -> toSQLId(functionName), + "inputType" -> toSQLType(inputType), + "castType" -> toSQLType(castType))) + } + def wrongCommandForObjectTypeError( operation: String, requiredType: String, diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala index 1d59c7a087869..d5719a35cb366 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala @@ -6916,6 +6916,17 @@ object SQLConf { .booleanConf .createWithDefault(false) + val LISTAGG_ALLOW_DISTINCT_CAST_WITH_ORDER = + buildConf("spark.sql.listagg.allowDistinctCastWithOrder.enabled") + .internal() + .doc("When true, LISTAGG(DISTINCT expr) WITHIN GROUP (ORDER BY expr) is allowed on " + + "non-string expr when the implicit cast to string preserves equality (e.g., integer, " + + "decimal, date). When false, the function argument and ORDER BY expression must have " + + "the exact same type, which requires explicit casts.") + .version("4.2.0") + .booleanConf + .createWithDefault(true) + /** * Holds information about keys that have been deprecated. * @@ -8144,6 +8155,8 @@ class SQLConf extends Serializable with Logging with SqlApiConf { def isTimeTypeEnabled: Boolean = getConf(SQLConf.TIME_TYPE_ENABLED) + def listaggAllowDistinctCastWithOrder: Boolean = getConf(LISTAGG_ALLOW_DISTINCT_CAST_WITH_ORDER) + /** ********************** SQLConf functionality methods ************ */ /** Set Spark SQL configuration properties. */ diff --git a/sql/core/src/test/resources/sql-tests/analyzer-results/listagg-collations.sql.out b/sql/core/src/test/resources/sql-tests/analyzer-results/listagg-collations.sql.out index 7a7d7aa3f0472..ebf428339c7ac 100644 --- a/sql/core/src/test/resources/sql-tests/analyzer-results/listagg-collations.sql.out +++ b/sql/core/src/test/resources/sql-tests/analyzer-results/listagg-collations.sql.out @@ -118,3 +118,72 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException "orderingExpr" : "\"collate(c1, utf8_binary)\"" } } + + +-- !query +SELECT listagg(DISTINCT CAST(col AS STRING)) WITHIN GROUP (ORDER BY col) FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), null, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT CAST(col AS STRING), NULL) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT CAST(col AS STRING COLLATE UTF8_LCASE)) WITHIN GROUP (ORDER BY col) FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col) +-- !query analysis +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"STRING COLLATE UTF8_LCASE\"", + "funcName" : "`listagg`", + "inputType" : "\"STRING\"" + } +} + + +-- !query +SELECT listagg(DISTINCT CAST(col AS STRING)) WITHIN GROUP (ORDER BY col) FROM VALUES (X'414243'), (X'616263'), (X'414243') AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), null, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT CAST(col AS STRING), NULL) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT CAST(col AS STRING COLLATE UTF8_LCASE)) WITHIN GROUP (ORDER BY col) FROM VALUES (X'414243'), (X'616263'), (X'414243') AS t(col) +-- !query analysis +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"STRING COLLATE UTF8_LCASE\"", + "funcName" : "`listagg`", + "inputType" : "\"BINARY\"" + } +} + + +-- !query +SELECT listagg(DISTINCT CAST(col AS BINARY)) WITHIN GROUP (ORDER BY col) FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as binary), null, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT CAST(col AS BINARY), NULL) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT CAST(col AS BINARY)) WITHIN GROUP (ORDER BY col) FROM (SELECT col COLLATE UTF8_LCASE AS col FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col)) +-- !query analysis +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"BINARY\"", + "funcName" : "`listagg`", + "inputType" : "\"STRING COLLATE UTF8_LCASE\"" + } +} diff --git a/sql/core/src/test/resources/sql-tests/analyzer-results/listagg.sql.out b/sql/core/src/test/resources/sql-tests/analyzer-results/listagg.sql.out index 1d78d882cf6a8..146aa9ff6f521 100644 --- a/sql/core/src/test/resources/sql-tests/analyzer-results/listagg.sql.out +++ b/sql/core/src/test/resources/sql-tests/analyzer-results/listagg.sql.out @@ -272,7 +272,7 @@ Aggregate [listagg(col1#x, null, col2#x DESC NULLS LAST, col1#x DESC NULLS LAST, -- !query -WITH t(col) AS (SELECT listagg(col1) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(col, X'DEAD'), regexp_count(col, X'BEEF') FROM t +WITH t(col) AS (SELECT listagg(col1) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')) FROM t -- !query analysis WithCTE :- CTERelationDef xxxx, false @@ -281,13 +281,13 @@ WithCTE : +- Aggregate [listagg(col1#x, null, 0, 0) AS listagg(col1, NULL)#x] : +- SubqueryAlias __auto_generated_subquery_name : +- LocalRelation [col1#x] -+- Project [len(col#x) AS len(col)#x, regexp_count(cast(col#x as string), cast(0xDEAD as string)) AS regexp_count(col, X'DEAD')#x, regexp_count(cast(col#x as string), cast(0xBEEF as string)) AS regexp_count(col, X'BEEF')#x] ++- Project [len(col#x) AS len(col)#x, regexp_count(hex(col#x), hex(0xDEAD)) AS regexp_count(hex(col), hex(X'DEAD'))#x, regexp_count(hex(col#x), hex(0xBEEF)) AS regexp_count(hex(col), hex(X'BEEF'))#x] +- SubqueryAlias t +- CTERelationRef xxxx, true, [col#x], false, false, 1 -- !query -WITH t(col) AS (SELECT listagg(col1, NULL) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(col, X'DEAD'), regexp_count(col, X'BEEF') FROM t +WITH t(col) AS (SELECT listagg(col1, NULL) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')) FROM t -- !query analysis WithCTE :- CTERelationDef xxxx, false @@ -296,13 +296,13 @@ WithCTE : +- Aggregate [listagg(col1#x, null, 0, 0) AS listagg(col1, NULL)#x] : +- SubqueryAlias __auto_generated_subquery_name : +- LocalRelation [col1#x] -+- Project [len(col#x) AS len(col)#x, regexp_count(cast(col#x as string), cast(0xDEAD as string)) AS regexp_count(col, X'DEAD')#x, regexp_count(cast(col#x as string), cast(0xBEEF as string)) AS regexp_count(col, X'BEEF')#x] ++- Project [len(col#x) AS len(col)#x, regexp_count(hex(col#x), hex(0xDEAD)) AS regexp_count(hex(col), hex(X'DEAD'))#x, regexp_count(hex(col#x), hex(0xBEEF)) AS regexp_count(hex(col), hex(X'BEEF'))#x] +- SubqueryAlias t +- CTERelationRef xxxx, true, [col#x], false, false, 1 -- !query -WITH t(col) AS (SELECT listagg(col1, X'42') FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(col, X'42'), regexp_count(col, X'DEAD'), regexp_count(col, X'BEEF') FROM t +WITH t(col) AS (SELECT listagg(col1, X'42') FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(hex(col), hex(X'42')), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')) FROM t -- !query analysis WithCTE :- CTERelationDef xxxx, false @@ -311,7 +311,7 @@ WithCTE : +- Aggregate [listagg(col1#x, 0x42, 0, 0) AS listagg(col1, X'42')#x] : +- SubqueryAlias __auto_generated_subquery_name : +- LocalRelation [col1#x] -+- Project [len(col#x) AS len(col)#x, regexp_count(cast(col#x as string), cast(0x42 as string)) AS regexp_count(col, X'42')#x, regexp_count(cast(col#x as string), cast(0xDEAD as string)) AS regexp_count(col, X'DEAD')#x, regexp_count(cast(col#x as string), cast(0xBEEF as string)) AS regexp_count(col, X'BEEF')#x] ++- Project [len(col#x) AS len(col)#x, regexp_count(hex(col#x), hex(0x42)) AS regexp_count(hex(col), hex(X'42'))#x, regexp_count(hex(col#x), hex(0xDEAD)) AS regexp_count(hex(col), hex(X'DEAD'))#x, regexp_count(hex(col#x), hex(0xBEEF)) AS regexp_count(hex(col), hex(X'BEEF'))#x] +- SubqueryAlias t +- CTERelationRef xxxx, true, [col#x], false, false, 1 @@ -335,6 +335,156 @@ WithCTE +- CTERelationRef xxxx, true, [col1#x, col2#x], false, false, 1 +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (1), (2), (2), (3) AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1 as bigint)), (cast(2 as bigint)), (cast(2 as bigint)), (cast(3 as bigint)) AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#xL as string), ,, col#xL ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#xL] + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1 as smallint)), (cast(2 as smallint)), (cast(2 as smallint)), (cast(3 as smallint)) AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1 as tinyint)), (cast(2 as tinyint)), (cast(2 as tinyint)), (cast(3 as tinyint)) AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1.10 as decimal(10,2))), (cast(2.20 as decimal(10,2))), (cast(2.20 as decimal(10,2))) AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (DATE'2024-01-01'), (DATE'2024-01-02'), (DATE'2024-01-01') AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (TIMESTAMP_NTZ'2024-01-01 10:00:00'), (TIMESTAMP_NTZ'2024-01-02 12:00:00'), (TIMESTAMP_NTZ'2024-01-01 10:00:00') AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (true), (false), (true) AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (INTERVAL '1' MONTH), (INTERVAL '2' MONTH), (INTERVAL '1' MONTH) AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT cast(col as string), ',') WITHIN GROUP (ORDER BY col) FROM VALUES (10), (1), (2), (20), (2) AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT CAST(col AS STRING), ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col DESC) FROM VALUES (1), (10), (2), (20), (2) AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x DESC NULLS LAST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col DESC NULLS LAST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (1), (2), (null), (2), (3) AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col NULLS FIRST) FROM VALUES (1), (null), (2), (null) AS t(col) +-- !query analysis +Aggregate [listagg(distinct cast(col#x as string), ,, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, ,) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [col#x] + + +-- !query +SELECT grp, listagg(DISTINCT col) WITHIN GROUP (ORDER BY col) FROM VALUES (1, 'a'), (1, 'b'), (2, 'a'), (2, 'a'), (1, 'b') AS t(grp, col) GROUP BY grp +-- !query analysis +Aggregate [grp#x], [grp#x, listagg(distinct col#x, null, col#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col, NULL) WITHIN GROUP (ORDER BY col ASC NULLS FIRST)#x] ++- SubqueryAlias t + +- LocalRelation [grp#x, col#x] + + +-- !query +WITH t(col) AS (SELECT listagg(DISTINCT col1, X'2C') WITHIN GROUP (ORDER BY col1) FROM (VALUES (X'DEAD'), (X'BEEF'), (X'DEAD'), (X'CAFE'))) SELECT len(col), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')), regexp_count(hex(col), hex(X'CAFE')) FROM t +-- !query analysis +WithCTE +:- CTERelationDef xxxx, false +: +- SubqueryAlias t +: +- Project [listagg(DISTINCT col1, X'2C') WITHIN GROUP (ORDER BY col1 ASC NULLS FIRST)#x AS col#x] +: +- Aggregate [listagg(distinct col1#x, 0x2C, col1#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col1, X'2C') WITHIN GROUP (ORDER BY col1 ASC NULLS FIRST)#x] +: +- SubqueryAlias __auto_generated_subquery_name +: +- LocalRelation [col1#x] ++- Project [len(col#x) AS len(col)#x, regexp_count(hex(col#x), hex(0xDEAD)) AS regexp_count(hex(col), hex(X'DEAD'))#x, regexp_count(hex(col#x), hex(0xBEEF)) AS regexp_count(hex(col), hex(X'BEEF'))#x, regexp_count(hex(col#x), hex(0xCAFE)) AS regexp_count(hex(col), hex(X'CAFE'))#x] + +- SubqueryAlias t + +- CTERelationRef xxxx, true, [col#x], false, false, 1 + + +-- !query +WITH t(col) AS (SELECT listagg(DISTINCT col1, X'7C') WITHIN GROUP (ORDER BY col1) FROM (VALUES (X'BB'), (X'AA'), (NULL), (X'BB'))) SELECT len(col), regexp_count(hex(col), hex(X'AA')), regexp_count(hex(col), hex(X'BB')) FROM t +-- !query analysis +WithCTE +:- CTERelationDef xxxx, false +: +- SubqueryAlias t +: +- Project [listagg(DISTINCT col1, X'7C') WITHIN GROUP (ORDER BY col1 ASC NULLS FIRST)#x AS col#x] +: +- Aggregate [listagg(distinct col1#x, 0x7C, col1#x ASC NULLS FIRST, 0, 0) AS listagg(DISTINCT col1, X'7C') WITHIN GROUP (ORDER BY col1 ASC NULLS FIRST)#x] +: +- SubqueryAlias __auto_generated_subquery_name +: +- LocalRelation [col1#x] ++- Project [len(col#x) AS len(col)#x, regexp_count(hex(col#x), hex(0xAA)) AS regexp_count(hex(col), hex(X'AA'))#x, regexp_count(hex(col#x), hex(0xBB)) AS regexp_count(hex(col), hex(X'BB'))#x] + +- SubqueryAlias t + +- CTERelationRef xxxx, true, [col#x], false, false, 1 + + +-- !query +SELECT grp, hex(listagg(DISTINCT col, X'2C') WITHIN GROUP (ORDER BY col)) FROM VALUES (1, X'AA'), (1, X'BB'), (1, X'AA'), (2, X'CC'), (2, X'CC') AS t(grp, col) GROUP BY grp +-- !query analysis +Aggregate [grp#x], [grp#x, hex(listagg(distinct col#x, 0x2C, col#x ASC NULLS FIRST, 0, 0)) AS hex(listagg(DISTINCT col, X'2C') WITHIN GROUP (ORDER BY col ASC NULLS FIRST))#x] ++- SubqueryAlias t + +- LocalRelation [grp#x, col#x] + + -- !query SELECT listagg(c1) FROM (VALUES (ARRAY('a', 'b'))) AS t(c1) -- !query analysis @@ -507,3 +657,48 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException "orderingExpr" : "\"col1\", \"col2\"" } } + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1.1 as double)), (cast(2.2 as double)), (cast(2.2 as double)), (cast(3.3 as double)) AS t(col) +-- !query analysis +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"STRING\"", + "funcName" : "`listagg`", + "inputType" : "\"DOUBLE\"" + } +} + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1.0 as float)), (cast(2.0 as float)), (cast(2.0 as float)) AS t(col) +-- !query analysis +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"STRING\"", + "funcName" : "`listagg`", + "inputType" : "\"FLOAT\"" + } +} + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (TIMESTAMP'2024-01-01 10:00:00'), (TIMESTAMP'2024-01-02 12:00:00'), (TIMESTAMP'2024-01-01 10:00:00') AS t(col) +-- !query analysis +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"STRING\"", + "funcName" : "`listagg`", + "inputType" : "\"TIMESTAMP\"" + } +} diff --git a/sql/core/src/test/resources/sql-tests/inputs/listagg-collations.sql b/sql/core/src/test/resources/sql-tests/inputs/listagg-collations.sql index aa3d02dc2fb66..86466711f93a5 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/listagg-collations.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/listagg-collations.sql @@ -12,3 +12,19 @@ WITH t(c1) AS (SELECT listagg(col1) WITHIN GROUP (ORDER BY col1 COLLATE unicode_ -- Error case with collations SELECT listagg(DISTINCT c1 COLLATE utf8_lcase) WITHIN GROUP (ORDER BY c1 COLLATE utf8_binary) FROM (VALUES ('a'), ('b'), ('A'), ('B')) AS t(c1); + +-- LISTAGG DISTINCT cast safety with collations: +-- string -> string (safe): explicit cast to same collation +SELECT listagg(DISTINCT CAST(col AS STRING)) WITHIN GROUP (ORDER BY col) FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col); +-- string -> string (unsafe): cast to non-binary-equality collation on target +SELECT listagg(DISTINCT CAST(col AS STRING COLLATE UTF8_LCASE)) WITHIN GROUP (ORDER BY col) FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col); + +-- binary -> string (safe): cast to default STRING (UTF8_BINARY) +SELECT listagg(DISTINCT CAST(col AS STRING)) WITHIN GROUP (ORDER BY col) FROM VALUES (X'414243'), (X'616263'), (X'414243') AS t(col); -- ABC, abc, ABC +-- binary -> string (unsafe): cast to non-binary-equality collation on target +SELECT listagg(DISTINCT CAST(col AS STRING COLLATE UTF8_LCASE)) WITHIN GROUP (ORDER BY col) FROM VALUES (X'414243'), (X'616263'), (X'414243') AS t(col); -- ABC, abc, ABC + +-- string -> binary (safe): UTF8_BINARY source, BinaryType target +SELECT listagg(DISTINCT CAST(col AS BINARY)) WITHIN GROUP (ORDER BY col) FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col); +-- string -> binary (unsafe): non-binary-equality source (UTF8_LCASE), BinaryType target +SELECT listagg(DISTINCT CAST(col AS BINARY)) WITHIN GROUP (ORDER BY col) FROM (SELECT col COLLATE UTF8_LCASE AS col FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col)) diff --git a/sql/core/src/test/resources/sql-tests/inputs/listagg.sql b/sql/core/src/test/resources/sql-tests/inputs/listagg.sql index 021de9975d308..3a7401893aaaf 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/listagg.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/listagg.sql @@ -24,11 +24,30 @@ WITH t(col) AS (SELECT listagg(col1, '|') WITHIN GROUP (ORDER BY col2 DESC) FROM SELECT listagg(col1, '|') WITHIN GROUP (ORDER BY col2 DESC) FROM df; SELECT listagg(col1) WITHIN GROUP (ORDER BY col2 DESC, col1 ASC) FROM df; SELECT listagg(col1) WITHIN GROUP (ORDER BY col2 DESC, col1 DESC) FROM df; -WITH t(col) AS (SELECT listagg(col1) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(col, X'DEAD'), regexp_count(col, X'BEEF') FROM t; -WITH t(col) AS (SELECT listagg(col1, NULL) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(col, X'DEAD'), regexp_count(col, X'BEEF') FROM t; -WITH t(col) AS (SELECT listagg(col1, X'42') FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(col, X'42'), regexp_count(col, X'DEAD'), regexp_count(col, X'BEEF') FROM t; +WITH t(col) AS (SELECT listagg(col1) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')) FROM t; +WITH t(col) AS (SELECT listagg(col1, NULL) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')) FROM t; +WITH t(col) AS (SELECT listagg(col1, X'42') FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(hex(col), hex(X'42')), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')) FROM t; WITH t(col1, col2) AS (SELECT listagg(col1), listagg(col2, ',') FROM df2) SELECT len(col1), regexp_count(col1, '1'), regexp_count(col1, '2'), regexp_count(col1, '3'), len(col2), regexp_count(col2, 'true'), regexp_count(col1, 'false') FROM t; +-- LISTAGG with DISTINCT with implicit cast from non-string types (safe types - should succeed) +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (1), (2), (2), (3) AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1 as bigint)), (cast(2 as bigint)), (cast(2 as bigint)), (cast(3 as bigint)) AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1 as smallint)), (cast(2 as smallint)), (cast(2 as smallint)), (cast(3 as smallint)) AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1 as tinyint)), (cast(2 as tinyint)), (cast(2 as tinyint)), (cast(3 as tinyint)) AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1.10 as decimal(10,2))), (cast(2.20 as decimal(10,2))), (cast(2.20 as decimal(10,2))) AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (DATE'2024-01-01'), (DATE'2024-01-02'), (DATE'2024-01-01') AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (TIMESTAMP_NTZ'2024-01-01 10:00:00'), (TIMESTAMP_NTZ'2024-01-02 12:00:00'), (TIMESTAMP_NTZ'2024-01-01 10:00:00') AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (true), (false), (true) AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (INTERVAL '1' MONTH), (INTERVAL '2' MONTH), (INTERVAL '1' MONTH) AS t(col); +SELECT listagg(DISTINCT cast(col as string), ',') WITHIN GROUP (ORDER BY col) FROM VALUES (10), (1), (2), (20), (2) AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col DESC) FROM VALUES (1), (10), (2), (20), (2) AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (1), (2), (null), (2), (3) AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col NULLS FIRST) FROM VALUES (1), (null), (2), (null) AS t(col); +SELECT grp, listagg(DISTINCT col) WITHIN GROUP (ORDER BY col) FROM VALUES (1, 'a'), (1, 'b'), (2, 'a'), (2, 'a'), (1, 'b') AS t(grp, col) GROUP BY grp; +WITH t(col) AS (SELECT listagg(DISTINCT col1, X'2C') WITHIN GROUP (ORDER BY col1) FROM (VALUES (X'DEAD'), (X'BEEF'), (X'DEAD'), (X'CAFE'))) SELECT len(col), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')), regexp_count(hex(col), hex(X'CAFE')) FROM t; +WITH t(col) AS (SELECT listagg(DISTINCT col1, X'7C') WITHIN GROUP (ORDER BY col1) FROM (VALUES (X'BB'), (X'AA'), (NULL), (X'BB'))) SELECT len(col), regexp_count(hex(col), hex(X'AA')), regexp_count(hex(col), hex(X'BB')) FROM t; +SELECT grp, hex(listagg(DISTINCT col, X'2C') WITHIN GROUP (ORDER BY col)) FROM VALUES (1, X'AA'), (1, X'BB'), (1, X'AA'), (2, X'CC'), (2, X'CC') AS t(grp, col) GROUP BY grp; + -- Error cases SELECT listagg(c1) FROM (VALUES (ARRAY('a', 'b'))) AS t(c1); SELECT listagg(c1, ', ') FROM (VALUES (X'DEAD'), (X'BEEF')) AS t(c1); @@ -39,3 +58,6 @@ SELECT string_agg(col1) WITHIN GROUP (ORDER BY col1) OVER (ORDER BY col1) FROM d SELECT listagg(DISTINCT col1) OVER (ORDER BY col1) FROM df; SELECT listagg(DISTINCT col1) WITHIN GROUP (ORDER BY col2) FROM df; SELECT listagg(DISTINCT col1) WITHIN GROUP (ORDER BY col1, col2) FROM df; +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1.1 as double)), (cast(2.2 as double)), (cast(2.2 as double)), (cast(3.3 as double)) AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1.0 as float)), (cast(2.0 as float)), (cast(2.0 as float)) AS t(col); +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (TIMESTAMP'2024-01-01 10:00:00'), (TIMESTAMP'2024-01-02 12:00:00'), (TIMESTAMP'2024-01-01 10:00:00') AS t(col); diff --git a/sql/core/src/test/resources/sql-tests/results/listagg-collations.sql.out b/sql/core/src/test/resources/sql-tests/results/listagg-collations.sql.out index 1f8c5822e7d84..6e826a3ed9be6 100644 --- a/sql/core/src/test/resources/sql-tests/results/listagg-collations.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/listagg-collations.sql.out @@ -80,3 +80,78 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException "orderingExpr" : "\"collate(c1, utf8_binary)\"" } } + + +-- !query +SELECT listagg(DISTINCT CAST(col AS STRING)) WITHIN GROUP (ORDER BY col) FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col) +-- !query schema +struct +-- !query output +ABCabc + + +-- !query +SELECT listagg(DISTINCT CAST(col AS STRING COLLATE UTF8_LCASE)) WITHIN GROUP (ORDER BY col) FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col) +-- !query schema +struct<> +-- !query output +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"STRING COLLATE UTF8_LCASE\"", + "funcName" : "`listagg`", + "inputType" : "\"STRING\"" + } +} + + +-- !query +SELECT listagg(DISTINCT CAST(col AS STRING)) WITHIN GROUP (ORDER BY col) FROM VALUES (X'414243'), (X'616263'), (X'414243') AS t(col) +-- !query schema +struct +-- !query output +ABCabc + + +-- !query +SELECT listagg(DISTINCT CAST(col AS STRING COLLATE UTF8_LCASE)) WITHIN GROUP (ORDER BY col) FROM VALUES (X'414243'), (X'616263'), (X'414243') AS t(col) +-- !query schema +struct<> +-- !query output +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"STRING COLLATE UTF8_LCASE\"", + "funcName" : "`listagg`", + "inputType" : "\"BINARY\"" + } +} + + +-- !query +SELECT listagg(DISTINCT CAST(col AS BINARY)) WITHIN GROUP (ORDER BY col) FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col) +-- !query schema +struct +-- !query output +ABCabc + + +-- !query +SELECT listagg(DISTINCT CAST(col AS BINARY)) WITHIN GROUP (ORDER BY col) FROM (SELECT col COLLATE UTF8_LCASE AS col FROM VALUES ('ABC'), ('abc'), ('ABC') AS t(col)) +-- !query schema +struct<> +-- !query output +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"BINARY\"", + "funcName" : "`listagg`", + "inputType" : "\"STRING COLLATE UTF8_LCASE\"" + } +} diff --git a/sql/core/src/test/resources/sql-tests/results/listagg.sql.out b/sql/core/src/test/resources/sql-tests/results/listagg.sql.out index 22ffceedb627d..ca387fe70fa13 100644 --- a/sql/core/src/test/resources/sql-tests/results/listagg.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/listagg.sql.out @@ -158,25 +158,25 @@ bbaa -- !query -WITH t(col) AS (SELECT listagg(col1) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(col, X'DEAD'), regexp_count(col, X'BEEF') FROM t +WITH t(col) AS (SELECT listagg(col1) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')) FROM t -- !query schema -struct +struct -- !query output 4 1 1 -- !query -WITH t(col) AS (SELECT listagg(col1, NULL) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(col, X'DEAD'), regexp_count(col, X'BEEF') FROM t +WITH t(col) AS (SELECT listagg(col1, NULL) FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')) FROM t -- !query schema -struct +struct -- !query output 4 1 1 -- !query -WITH t(col) AS (SELECT listagg(col1, X'42') FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(col, X'42'), regexp_count(col, X'DEAD'), regexp_count(col, X'BEEF') FROM t +WITH t(col) AS (SELECT listagg(col1, X'42') FROM (VALUES (X'DEAD'), (X'BEEF'))) SELECT len(col), regexp_count(hex(col), hex(X'42')), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')) FROM t -- !query schema -struct +struct -- !query output 5 1 1 1 @@ -189,6 +189,144 @@ struct +-- !query output +1,2,3 + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1 as bigint)), (cast(2 as bigint)), (cast(2 as bigint)), (cast(3 as bigint)) AS t(col) +-- !query schema +struct +-- !query output +1,2,3 + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1 as smallint)), (cast(2 as smallint)), (cast(2 as smallint)), (cast(3 as smallint)) AS t(col) +-- !query schema +struct +-- !query output +1,2,3 + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1 as tinyint)), (cast(2 as tinyint)), (cast(2 as tinyint)), (cast(3 as tinyint)) AS t(col) +-- !query schema +struct +-- !query output +1,2,3 + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1.10 as decimal(10,2))), (cast(2.20 as decimal(10,2))), (cast(2.20 as decimal(10,2))) AS t(col) +-- !query schema +struct +-- !query output +1.10,2.20 + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (DATE'2024-01-01'), (DATE'2024-01-02'), (DATE'2024-01-01') AS t(col) +-- !query schema +struct +-- !query output +2024-01-01,2024-01-02 + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (TIMESTAMP_NTZ'2024-01-01 10:00:00'), (TIMESTAMP_NTZ'2024-01-02 12:00:00'), (TIMESTAMP_NTZ'2024-01-01 10:00:00') AS t(col) +-- !query schema +struct +-- !query output +2024-01-01 10:00:00,2024-01-02 12:00:00 + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (true), (false), (true) AS t(col) +-- !query schema +struct +-- !query output +false,true + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (INTERVAL '1' MONTH), (INTERVAL '2' MONTH), (INTERVAL '1' MONTH) AS t(col) +-- !query schema +struct +-- !query output +INTERVAL '1' MONTH,INTERVAL '2' MONTH + + +-- !query +SELECT listagg(DISTINCT cast(col as string), ',') WITHIN GROUP (ORDER BY col) FROM VALUES (10), (1), (2), (20), (2) AS t(col) +-- !query schema +struct +-- !query output +1,2,10,20 + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col DESC) FROM VALUES (1), (10), (2), (20), (2) AS t(col) +-- !query schema +struct +-- !query output +20,10,2,1 + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (1), (2), (null), (2), (3) AS t(col) +-- !query schema +struct +-- !query output +1,2,3 + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col NULLS FIRST) FROM VALUES (1), (null), (2), (null) AS t(col) +-- !query schema +struct +-- !query output +1,2 + + +-- !query +SELECT grp, listagg(DISTINCT col) WITHIN GROUP (ORDER BY col) FROM VALUES (1, 'a'), (1, 'b'), (2, 'a'), (2, 'a'), (1, 'b') AS t(grp, col) GROUP BY grp +-- !query schema +struct +-- !query output +1 ab +2 a + + +-- !query +WITH t(col) AS (SELECT listagg(DISTINCT col1, X'2C') WITHIN GROUP (ORDER BY col1) FROM (VALUES (X'DEAD'), (X'BEEF'), (X'DEAD'), (X'CAFE'))) SELECT len(col), regexp_count(hex(col), hex(X'DEAD')), regexp_count(hex(col), hex(X'BEEF')), regexp_count(hex(col), hex(X'CAFE')) FROM t +-- !query schema +struct +-- !query output +8 1 1 1 + + +-- !query +WITH t(col) AS (SELECT listagg(DISTINCT col1, X'7C') WITHIN GROUP (ORDER BY col1) FROM (VALUES (X'BB'), (X'AA'), (NULL), (X'BB'))) SELECT len(col), regexp_count(hex(col), hex(X'AA')), regexp_count(hex(col), hex(X'BB')) FROM t +-- !query schema +struct +-- !query output +3 1 1 + + +-- !query +SELECT grp, hex(listagg(DISTINCT col, X'2C') WITHIN GROUP (ORDER BY col)) FROM VALUES (1, X'AA'), (1, X'BB'), (1, X'AA'), (2, X'CC'), (2, X'CC') AS t(grp, col) GROUP BY grp +-- !query schema +struct +-- !query output +1 AA2CBB +2 CC + + -- !query SELECT listagg(c1) FROM (VALUES (ARRAY('a', 'b'))) AS t(c1) -- !query schema @@ -374,3 +512,54 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException "orderingExpr" : "\"col1\", \"col2\"" } } + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1.1 as double)), (cast(2.2 as double)), (cast(2.2 as double)), (cast(3.3 as double)) AS t(col) +-- !query schema +struct<> +-- !query output +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"STRING\"", + "funcName" : "`listagg`", + "inputType" : "\"DOUBLE\"" + } +} + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (cast(1.0 as float)), (cast(2.0 as float)), (cast(2.0 as float)) AS t(col) +-- !query schema +struct<> +-- !query output +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"STRING\"", + "funcName" : "`listagg`", + "inputType" : "\"FLOAT\"" + } +} + + +-- !query +SELECT listagg(DISTINCT col, ',') WITHIN GROUP (ORDER BY col) FROM VALUES (TIMESTAMP'2024-01-01 10:00:00'), (TIMESTAMP'2024-01-02 12:00:00'), (TIMESTAMP'2024-01-01 10:00:00') AS t(col) +-- !query schema +struct<> +-- !query output +org.apache.spark.sql.catalyst.ExtendedAnalysisException +{ + "errorClass" : "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT_UNSAFE_CAST", + "sqlState" : "42K0K", + "messageParameters" : { + "castType" : "\"STRING\"", + "funcName" : "`listagg`", + "inputType" : "\"TIMESTAMP\"" + } +} diff --git a/sql/core/src/test/scala/org/apache/spark/sql/DataFrameAggregateSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/DataFrameAggregateSuite.scala index f606c6746f3c2..355333d8268f5 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/DataFrameAggregateSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/DataFrameAggregateSuite.scala @@ -709,6 +709,31 @@ class DataFrameAggregateSuite extends QueryTest ) } + test("SPARK-55501: listagg with DISTINCT and ORDER BY") { + val df = Seq(1, 2, 10, 1, 9).toDF("a") + + withSQLConf(SQLConf.LISTAGG_ALLOW_DISTINCT_CAST_WITH_ORDER.key -> "true") { + checkAnswer( + df.selectExpr("listagg(distinct a, ', ') within group (order by a)"), + Seq(Row("1, 2, 9, 10")) + ) + } + + withSQLConf(SQLConf.LISTAGG_ALLOW_DISTINCT_CAST_WITH_ORDER.key -> "false") { + checkError( + exception = intercept[AnalysisException] { + df.selectExpr("listagg(distinct a) within group (order by a)") + }, + condition = "INVALID_WITHIN_GROUP_EXPRESSION.MISMATCH_WITH_DISTINCT_INPUT", + parameters = Map( + "funcName" -> "`listagg`", + "funcArg" -> "\"a\"", + "orderingExpr" -> "\"a\"" + ) + ) + } + } + test("SPARK-31500: collect_set() of BinaryType returns duplicate elements") { val bytesTest1 = "test1".getBytes val bytesTest2 = "test2".getBytes From 4b65223e020756aa47f647acc22112458d3e7569 Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Sat, 28 Feb 2026 06:45:46 -0800 Subject: [PATCH 094/130] [SPARK-55639][K8S] Support Recovery-mode K8s Executors ### What changes were proposed in this pull request? This PR aims to support `Recovery-mode` K8s Executors. ### Why are the changes needed? Frequently, Spark jobs have skewed data and corresponding tasks. In the worst case, a single resource-hungry task becomes a serial killer of executors. The homogeneous executors are unable to handle this kind of situation. So, this PR introduces a **recovery-mode executor** when Spark driver detects `OOM` situation from the failed executors. A recovery-mode executor aims to provide an executor serving only a single task. In other words, after OOM, new executor will be created with the same pod spec (memory and core) except `ENV_EXECUTOR_CORES=spark.task.cpus` environment variable setting to allow a single task per executor JVM. **EXAMPLE: OOM happens at `Executor 1` and `Executor 3` is created as the recover mode** Screenshot 2026-02-28 at 06 38 39 ### Does this PR introduce _any_ user-facing change? - There is no behavior change for a healthy job with no executor loss. - There is no behavior change for jobs with non-OOM executor loss. - For the failed job due to OOM, this PR only tries to mitigate the situation by trying to make the job to finish. - If the OOM happens even on the recovery-mode executor (a single task per executor JVM). The job will fail again. - If the recovery-mode executor can handle those skewed tasks, this job will succeed which is good. - For the faulty job with one or two OOM-driven executor loss, this PR only affects newly created pods (which are one or two as we assumed). So, technically, the job will succeed in the very similar way because the most of executors are the same. - `spark.kubernetes.allocation.recoveryMode.enabled=false` will disable the whole feature. ### How was this patch tested? Pass the CIs with newly added test cases. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity` Closes #54558 from dongjoon-hyun/SPARK-55639-2. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- .../org/apache/spark/deploy/k8s/Config.scala | 11 ++++++++++ .../features/BasicExecutorFeatureStep.scala | 8 ++++++- .../cluster/k8s/ExecutorPodsAllocator.scala | 4 ++++ .../KubernetesClusterSchedulerBackend.scala | 7 +++++- .../BasicExecutorFeatureStepSuite.scala | 22 +++++++++++++++++++ .../k8s/ExecutorPodsAllocatorSuite.scala | 8 +++++++ ...bernetesClusterSchedulerBackendSuite.scala | 15 ++++++++++++- 7 files changed, 72 insertions(+), 3 deletions(-) diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/Config.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/Config.scala index 5c26dea417acc..6f1130853c5a1 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/Config.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/Config.scala @@ -521,6 +521,17 @@ private[spark] object Config extends Logging { .checkValue(value => value > 100, "Allocation batch delay must be greater than 0.1s.") .createWithDefaultString("1s") + val KUBERNETES_ALLOCATION_RECOVERY_MODE_ENABLED = + ConfigBuilder("spark.kubernetes.allocation.recoveryMode.enabled") + .doc("When Spark driver detects an executor termination due to OOM, Spark starts to " + + "allocate the recovery-mode executors which accept only a single task per executor JVM. " + + "In other words, the recovery-mode executors replace the OOM-terminated executors to " + + "survive from the resource-hungry tasks for the remaining tasks and stages. " + + "If set to `false`, Spark will not use the recovery-mode executors.") + .version("4.2.0") + .booleanConf + .createOptional + val KUBERNETES_ALLOCATION_MAXIMUM = ConfigBuilder("spark.kubernetes.allocation.maximum") .doc("The maximum number of executor pods to try to create during the whole job lifecycle.") diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/BasicExecutorFeatureStep.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/BasicExecutorFeatureStep.scala index 2e8690fc33bd8..655df6c5acad6 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/BasicExecutorFeatureStep.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/BasicExecutorFeatureStep.scala @@ -164,7 +164,13 @@ private[spark] class BasicExecutorFeatureStep( KubernetesUtils.buildEnvVars( Seq( ENV_DRIVER_URL -> driverUrl, - ENV_EXECUTOR_CORES -> execResources.cores.get.toString, + ENV_EXECUTOR_CORES -> { + if (kubernetesConf.get(KUBERNETES_ALLOCATION_RECOVERY_MODE_ENABLED).getOrElse(false)) { + kubernetesConf.get("spark.task.cpus", "1") + } else { + execResources.cores.get.toString + } + }, ENV_EXECUTOR_MEMORY -> executorMemoryString, ENV_APPLICATION_ID -> kubernetesConf.appId, // This is to set the SPARK_CONF_DIR to be /opt/spark/conf diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocator.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocator.scala index 340cc9c76e46f..9322970e6b98e 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocator.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocator.scala @@ -429,6 +429,10 @@ class ExecutorPodsAllocator( } } + def setRecoveryMode(): Unit = { + conf.setIfMissing(KUBERNETES_ALLOCATION_RECOVERY_MODE_ENABLED, true) + } + protected def requestNewExecutors( numExecutorsToAllocate: Int, applicationId: String, diff --git a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterSchedulerBackend.scala b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterSchedulerBackend.scala index fa5e959276f54..71ed4a6a5aee0 100644 --- a/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterSchedulerBackend.scala +++ b/resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterSchedulerBackend.scala @@ -71,9 +71,14 @@ private[spark] class KubernetesClusterSchedulerBackend( private val PATCH_CONTEXT = PatchContext.of(PatchType.STRATEGIC_MERGE) - // Allow removeExecutor to be accessible by ExecutorPodsLifecycleManager private[k8s] def doRemoveExecutor(executorId: String, reason: ExecutorLossReason): Unit = { removeExecutor(executorId, reason) + podAllocator match { + case allocator: ExecutorPodsAllocator if reason.message.contains("OOM") => + logWarning("OOM is detected.") + allocator.setRecoveryMode() + case _ => // no-op + } } private def setUpExecutorConfigMap(driverPod: Option[Pod]): Unit = { diff --git a/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/features/BasicExecutorFeatureStepSuite.scala b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/features/BasicExecutorFeatureStepSuite.scala index 4ab9f3a72d34d..77dcb11ba43b0 100644 --- a/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/features/BasicExecutorFeatureStepSuite.scala +++ b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/features/BasicExecutorFeatureStepSuite.scala @@ -668,6 +668,28 @@ class BasicExecutorFeatureStepSuite extends SparkFunSuite with BeforeAndAfter { assert(memoryPolicy.get.getRestartPolicy === "NotRequired") } + test("SPARK-55639: ENV_EXECUTOR_CORES is spark.task.cpus when recoveryMode is enabled") { + val rpb = new ResourceProfileBuilder() + val ereq = new ExecutorResourceRequests() + val treq = new TaskResourceRequests() + ereq.cores(4) + treq.cpus(2) + rpb.require(ereq).require(treq) + val rp = rpb.build() + + var step = new BasicExecutorFeatureStep(newExecutorConf(), new SecurityManager(baseConf), rp) + var executor = step.configurePod(SparkPod.initialPod()) + var cores = executor.container.getEnv.asScala.find(_.getName == ENV_EXECUTOR_CORES).get.getValue + assert(cores === "4") + + baseConf.set(KUBERNETES_ALLOCATION_RECOVERY_MODE_ENABLED, true) + baseConf.set("spark.task.cpus", "2") + step = new BasicExecutorFeatureStep(newExecutorConf(), new SecurityManager(baseConf), rp) + executor = step.configurePod(SparkPod.initialPod()) + cores = executor.container.getEnv.asScala.find(_.getName == ENV_EXECUTOR_CORES).get.getValue + assert(cores === "2") + } + // There is always exactly one controller reference, and it points to the driver pod. private def checkOwnerReferences(executor: Pod, driverPodUid: String): Unit = { assert(executor.getMetadata.getOwnerReferences.size() === 1) diff --git a/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocatorSuite.scala b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocatorSuite.scala index fcdf248b2a22c..3f2e344b1c230 100644 --- a/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocatorSuite.scala +++ b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/ExecutorPodsAllocatorSuite.scala @@ -1080,4 +1080,12 @@ class ExecutorPodsAllocatorSuite extends SparkFunSuite with BeforeAndAfter { // Verify no pods were created since all attempts failed assert(podsAllocatorUnderTest.invokePrivate(numOutstandingPods).get() == 0) } + + test("SPARK-55639: setRecoveryMode should not change recovery mode if it is already false") { + val newConf = conf.clone.set(KUBERNETES_ALLOCATION_RECOVERY_MODE_ENABLED, false) + val podsAllocator = new ExecutorPodsAllocator(newConf, secMgr, executorBuilder, + kubernetesClient, snapshotsStore, waitForExecutorPodsClock) + podsAllocator.setRecoveryMode() + assert(!newConf.get(KUBERNETES_ALLOCATION_RECOVERY_MODE_ENABLED).get) + } } diff --git a/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterSchedulerBackendSuite.scala b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterSchedulerBackendSuite.scala index 0f975f71275f2..c7165b81671ad 100644 --- a/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterSchedulerBackendSuite.scala +++ b/resource-managers/kubernetes/core/src/test/scala/org/apache/spark/scheduler/cluster/k8s/KubernetesClusterSchedulerBackendSuite.scala @@ -37,7 +37,7 @@ import org.apache.spark.deploy.k8s.Constants._ import org.apache.spark.deploy.k8s.Fabric8Aliases._ import org.apache.spark.resource.{ResourceProfile, ResourceProfileManager} import org.apache.spark.rpc.{RpcCallContext, RpcEndpoint, RpcEndpointRef, RpcEnv} -import org.apache.spark.scheduler.{ExecutorKilled, LiveListenerBus, TaskSchedulerImpl} +import org.apache.spark.scheduler.{ExecutorKilled, ExecutorLossReason, LiveListenerBus, TaskSchedulerImpl} import org.apache.spark.scheduler.cluster.CoarseGrainedClusterMessages.{RegisterExecutor, RemoveExecutor, StopDriver} import org.apache.spark.scheduler.cluster.CoarseGrainedSchedulerBackend import org.apache.spark.scheduler.cluster.k8s.ExecutorLifecycleTestUtils.TEST_SPARK_APP_ID @@ -189,6 +189,19 @@ class KubernetesClusterSchedulerBackendSuite extends SparkFunSuite with BeforeAn verify(driverEndpointRef).send(RemoveExecutor("2", ExecutorKilled)) } + test("SPARK-55639: doRemoveExecutor triggers setRecoveryMode on OOM") { + val backend = spy[KubernetesClusterSchedulerBackend](schedulerBackendUnderTest) + when(backend.isExecutorActive(any())).thenReturn(false) + backend.start() + + val reason = mock(classOf[ExecutorLossReason]) + when(reason.message).thenReturn("Executor lost due to OOM") + + backend.doRemoveExecutor("1", reason) + verify(driverEndpointRef).send(RemoveExecutor("1", reason)) + verify(podAllocator).setRecoveryMode() + } + test("Kill executors") { schedulerBackendUnderTest.start() From 40db51f26b004b44e2b4fe2a3843f89651d3070d Mon Sep 17 00:00:00 2001 From: Kent Yao Date: Sat, 28 Feb 2026 22:58:20 +0800 Subject: [PATCH 095/130] [SPARK-55752][UI] Upgrade D3.js to 7.9.0 and vis-timeline to 7.7.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? Update the Spark Web UI's JavaScript visualization libraries: - **D3.js**: 7.8.5 → 7.9.0 - **vis-timeline**: 7.7.2 → 7.7.3 ### Why are the changes needed? These are minor version bumps with no breaking API changes, bringing bug fixes and performance improvements. The current versions are slightly outdated. ### Does this PR introduce _any_ user-facing change? No. These are internal dependency updates with no visible behavior change. ### How was this patch tested? - All 12 Jest UI tests pass - Verified via live Spark Web UI (spark-shell) ### Was this patch authored or co-authored using generative AI tooling? Yes, GitHub Copilot was used. Closes #54551 from yaooqinn/ui-upgrade-d3-vis. Authored-by: Kent Yao Signed-off-by: Kent Yao --- .../org/apache/spark/ui/static/d3.min.js | 4 ++-- .../ui/static/vis-timeline-graph2d.min.css | 2 +- .../ui/static/vis-timeline-graph2d.min.js | 24 ++++++++++--------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/core/src/main/resources/org/apache/spark/ui/static/d3.min.js b/core/src/main/resources/org/apache/spark/ui/static/d3.min.js index 8d56002d90f37..33bb880268a54 100644 --- a/core/src/main/resources/org/apache/spark/ui/static/d3.min.js +++ b/core/src/main/resources/org/apache/spark/ui/static/d3.min.js @@ -1,2 +1,2 @@ -// https://d3js.org v7.8.5 Copyright 2010-2023 Mike Bostock -!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).d3=t.d3||{})}(this,(function(t){"use strict";function n(t,n){return null==t||null==n?NaN:tn?1:t>=n?0:NaN}function e(t,n){return null==t||null==n?NaN:nt?1:n>=t?0:NaN}function r(t){let r,o,a;function u(t,n,e=0,i=t.length){if(e>>1;o(t[r],n)<0?e=r+1:i=r}while(en(t(e),r),a=(n,e)=>t(n)-e):(r=t===n||t===e?t:i,o=t,a=t),{left:u,center:function(t,n,e=0,r=t.length){const i=u(t,n,e,r-1);return i>e&&a(t[i-1],n)>-a(t[i],n)?i-1:i},right:function(t,n,e=0,i=t.length){if(e>>1;o(t[r],n)<=0?e=r+1:i=r}while(e{n(t,e,(r<<=2)+0,(i<<=2)+0,o<<=2),n(t,e,r+1,i+1,o),n(t,e,r+2,i+2,o),n(t,e,r+3,i+3,o)}}));function d(t){return function(n,e,r=e){if(!((e=+e)>=0))throw new RangeError("invalid rx");if(!((r=+r)>=0))throw new RangeError("invalid ry");let{data:i,width:o,height:a}=n;if(!((o=Math.floor(o))>=0))throw new RangeError("invalid width");if(!((a=Math.floor(void 0!==a?a:i.length/o))>=0))throw new RangeError("invalid height");if(!o||!a||!e&&!r)return n;const u=e&&t(e),c=r&&t(r),f=i.slice();return u&&c?(p(u,f,i,o,a),p(u,i,f,o,a),p(u,f,i,o,a),g(c,i,f,o,a),g(c,f,i,o,a),g(c,i,f,o,a)):u?(p(u,i,f,o,a),p(u,f,i,o,a),p(u,i,f,o,a)):c&&(g(c,i,f,o,a),g(c,f,i,o,a),g(c,i,f,o,a)),n}}function p(t,n,e,r,i){for(let o=0,a=r*i;o{if(!((o-=a)>=i))return;let u=t*r[i];const c=a*t;for(let t=i,n=i+c;t{if(!((a-=u)>=o))return;let c=n*i[o];const f=u*n,s=f+u;for(let t=o,n=o+f;t=n&&++e;else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&(i=+i)>=i&&++e}return e}function _(t){return 0|t.length}function b(t){return!(t>0)}function m(t){return"object"!=typeof t||"length"in t?t:Array.from(t)}function x(t,n){let e,r=0,i=0,o=0;if(void 0===n)for(let n of t)null!=n&&(n=+n)>=n&&(e=n-i,i+=e/++r,o+=e*(n-i));else{let a=-1;for(let u of t)null!=(u=n(u,++a,t))&&(u=+u)>=u&&(e=u-i,i+=e/++r,o+=e*(u-i))}if(r>1)return o/(r-1)}function w(t,n){const e=x(t,n);return e?Math.sqrt(e):e}function M(t,n){let e,r;if(void 0===n)for(const n of t)null!=n&&(void 0===e?n>=n&&(e=r=n):(e>n&&(e=n),r=o&&(e=r=o):(e>o&&(e=o),r0){for(o=t[--i];i>0&&(n=o,e=t[--i],o=n+e,r=e-(o-n),!r););i>0&&(r<0&&t[i-1]<0||r>0&&t[i-1]>0)&&(e=2*r,n=o+e,e==n-o&&(o=n))}return o}}class InternMap extends Map{constructor(t,n=N){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:n}}),null!=t)for(const[n,e]of t)this.set(n,e)}get(t){return super.get(A(this,t))}has(t){return super.has(A(this,t))}set(t,n){return super.set(S(this,t),n)}delete(t){return super.delete(E(this,t))}}class InternSet extends Set{constructor(t,n=N){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:n}}),null!=t)for(const n of t)this.add(n)}has(t){return super.has(A(this,t))}add(t){return super.add(S(this,t))}delete(t){return super.delete(E(this,t))}}function A({_intern:t,_key:n},e){const r=n(e);return t.has(r)?t.get(r):e}function S({_intern:t,_key:n},e){const r=n(e);return t.has(r)?t.get(r):(t.set(r,e),e)}function E({_intern:t,_key:n},e){const r=n(e);return t.has(r)&&(e=t.get(r),t.delete(r)),e}function N(t){return null!==t&&"object"==typeof t?t.valueOf():t}function k(t){return t}function C(t,...n){return F(t,k,k,n)}function P(t,...n){return F(t,Array.from,k,n)}function z(t,n){for(let e=1,r=n.length;et.pop().map((([n,e])=>[...t,n,e]))));return t}function $(t,n,...e){return F(t,k,n,e)}function D(t,n,...e){return F(t,Array.from,n,e)}function R(t){if(1!==t.length)throw new Error("duplicate key");return t[0]}function F(t,n,e,r){return function t(i,o){if(o>=r.length)return e(i);const a=new InternMap,u=r[o++];let c=-1;for(const t of i){const n=u(t,++c,i),e=a.get(n);e?e.push(t):a.set(n,[t])}for(const[n,e]of a)a.set(n,t(e,o));return n(a)}(t,0)}function q(t,n){return Array.from(n,(n=>t[n]))}function U(t,...n){if("function"!=typeof t[Symbol.iterator])throw new TypeError("values is not iterable");t=Array.from(t);let[e]=n;if(e&&2!==e.length||n.length>1){const r=Uint32Array.from(t,((t,n)=>n));return n.length>1?(n=n.map((n=>t.map(n))),r.sort(((t,e)=>{for(const r of n){const n=O(r[t],r[e]);if(n)return n}}))):(e=t.map(e),r.sort(((t,n)=>O(e[t],e[n])))),q(t,r)}return t.sort(I(e))}function I(t=n){if(t===n)return O;if("function"!=typeof t)throw new TypeError("compare is not a function");return(n,e)=>{const r=t(n,e);return r||0===r?r:(0===t(e,e))-(0===t(n,n))}}function O(t,n){return(null==t||!(t>=t))-(null==n||!(n>=n))||(tn?1:0)}var B=Array.prototype.slice;function Y(t){return()=>t}const L=Math.sqrt(50),j=Math.sqrt(10),H=Math.sqrt(2);function X(t,n,e){const r=(n-t)/Math.max(0,e),i=Math.floor(Math.log10(r)),o=r/Math.pow(10,i),a=o>=L?10:o>=j?5:o>=H?2:1;let u,c,f;return i<0?(f=Math.pow(10,-i)/a,u=Math.round(t*f),c=Math.round(n*f),u/fn&&--c,f=-f):(f=Math.pow(10,i)*a,u=Math.round(t/f),c=Math.round(n/f),u*fn&&--c),c0))return[];if((t=+t)===(n=+n))return[t];const r=n=i))return[];const u=o-i+1,c=new Array(u);if(r)if(a<0)for(let t=0;t0?(t=Math.floor(t/i)*i,n=Math.ceil(n/i)*i):i<0&&(t=Math.ceil(t*i)/i,n=Math.floor(n*i)/i),r=i}}function K(t){return Math.max(1,Math.ceil(Math.log(v(t))/Math.LN2)+1)}function Q(){var t=k,n=M,e=K;function r(r){Array.isArray(r)||(r=Array.from(r));var i,o,a,u=r.length,c=new Array(u);for(i=0;i=h)if(t>=h&&n===M){const t=V(l,h,e);isFinite(t)&&(t>0?h=(Math.floor(h/t)+1)*t:t<0&&(h=(Math.ceil(h*-t)+1)/-t))}else d.pop()}for(var p=d.length,g=0,y=p;d[g]<=l;)++g;for(;d[y-1]>h;)--y;(g||y0?d[i-1]:l,v.x1=i0)for(i=0;i=n)&&(e=n);else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&(e=i)&&(e=i)}return e}function tt(t,n){let e,r=-1,i=-1;if(void 0===n)for(const n of t)++i,null!=n&&(e=n)&&(e=n,r=i);else for(let o of t)null!=(o=n(o,++i,t))&&(e=o)&&(e=o,r=i);return r}function nt(t,n){let e;if(void 0===n)for(const n of t)null!=n&&(e>n||void 0===e&&n>=n)&&(e=n);else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&(e>i||void 0===e&&i>=i)&&(e=i)}return e}function et(t,n){let e,r=-1,i=-1;if(void 0===n)for(const n of t)++i,null!=n&&(e>n||void 0===e&&n>=n)&&(e=n,r=i);else for(let o of t)null!=(o=n(o,++i,t))&&(e>o||void 0===e&&o>=o)&&(e=o,r=i);return r}function rt(t,n,e=0,r=1/0,i){if(n=Math.floor(n),e=Math.floor(Math.max(0,e)),r=Math.floor(Math.min(t.length-1,r)),!(e<=n&&n<=r))return t;for(i=void 0===i?O:I(i);r>e;){if(r-e>600){const o=r-e+1,a=n-e+1,u=Math.log(o),c=.5*Math.exp(2*u/3),f=.5*Math.sqrt(u*c*(o-c)/o)*(a-o/2<0?-1:1);rt(t,n,Math.max(e,Math.floor(n-a*c/o+f)),Math.min(r,Math.floor(n+(o-a)*c/o+f)),i)}const o=t[n];let a=e,u=r;for(it(t,e,n),i(t[r],o)>0&&it(t,e,r);a0;)--u}0===i(t[e],o)?it(t,e,u):(++u,it(t,u,r)),u<=n&&(e=u+1),n<=u&&(r=u-1)}return t}function it(t,n,e){const r=t[n];t[n]=t[e],t[e]=r}function ot(t,e=n){let r,i=!1;if(1===e.length){let o;for(const a of t){const t=e(a);(i?n(t,o)>0:0===n(t,t))&&(r=a,o=t,i=!0)}}else for(const n of t)(i?e(n,r)>0:0===e(n,n))&&(r=n,i=!0);return r}function at(t,n,e){if(t=Float64Array.from(function*(t,n){if(void 0===n)for(let n of t)null!=n&&(n=+n)>=n&&(yield n);else{let e=-1;for(let r of t)null!=(r=n(r,++e,t))&&(r=+r)>=r&&(yield r)}}(t,e)),(r=t.length)&&!isNaN(n=+n)){if(n<=0||r<2)return nt(t);if(n>=1)return J(t);var r,i=(r-1)*n,o=Math.floor(i),a=J(rt(t,o).subarray(0,o+1));return a+(nt(t.subarray(o+1))-a)*(i-o)}}function ut(t,n,e=o){if((r=t.length)&&!isNaN(n=+n)){if(n<=0||r<2)return+e(t[0],0,t);if(n>=1)return+e(t[r-1],r-1,t);var r,i=(r-1)*n,a=Math.floor(i),u=+e(t[a],a,t);return u+(+e(t[a+1],a+1,t)-u)*(i-a)}}function ct(t,n,e=o){if(!isNaN(n=+n)){if(r=Float64Array.from(t,((n,r)=>o(e(t[r],r,t)))),n<=0)return et(r);if(n>=1)return tt(r);var r,i=Uint32Array.from(t,((t,n)=>n)),a=r.length-1,u=Math.floor(a*n);return rt(i,u,0,a,((t,n)=>O(r[t],r[n]))),(u=ot(i.subarray(0,u+1),(t=>r[t])))>=0?u:-1}}function ft(t){return Array.from(function*(t){for(const n of t)yield*n}(t))}function st(t,n){return[t,n]}function lt(t,n,e){t=+t,n=+n,e=(i=arguments.length)<2?(n=t,t=0,1):i<3?1:+e;for(var r=-1,i=0|Math.max(0,Math.ceil((n-t)/e)),o=new Array(i);++r+t(n)}function kt(t,n){return n=Math.max(0,t.bandwidth()-2*n)/2,t.round()&&(n=Math.round(n)),e=>+t(e)+n}function Ct(){return!this.__axis}function Pt(t,n){var e=[],r=null,i=null,o=6,a=6,u=3,c="undefined"!=typeof window&&window.devicePixelRatio>1?0:.5,f=t===xt||t===Tt?-1:1,s=t===Tt||t===wt?"x":"y",l=t===xt||t===Mt?St:Et;function h(h){var d=null==r?n.ticks?n.ticks.apply(n,e):n.domain():r,p=null==i?n.tickFormat?n.tickFormat.apply(n,e):mt:i,g=Math.max(o,0)+u,y=n.range(),v=+y[0]+c,_=+y[y.length-1]+c,b=(n.bandwidth?kt:Nt)(n.copy(),c),m=h.selection?h.selection():h,x=m.selectAll(".domain").data([null]),w=m.selectAll(".tick").data(d,n).order(),M=w.exit(),T=w.enter().append("g").attr("class","tick"),A=w.select("line"),S=w.select("text");x=x.merge(x.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),w=w.merge(T),A=A.merge(T.append("line").attr("stroke","currentColor").attr(s+"2",f*o)),S=S.merge(T.append("text").attr("fill","currentColor").attr(s,f*g).attr("dy",t===xt?"0em":t===Mt?"0.71em":"0.32em")),h!==m&&(x=x.transition(h),w=w.transition(h),A=A.transition(h),S=S.transition(h),M=M.transition(h).attr("opacity",At).attr("transform",(function(t){return isFinite(t=b(t))?l(t+c):this.getAttribute("transform")})),T.attr("opacity",At).attr("transform",(function(t){var n=this.parentNode.__axis;return l((n&&isFinite(n=n(t))?n:b(t))+c)}))),M.remove(),x.attr("d",t===Tt||t===wt?a?"M"+f*a+","+v+"H"+c+"V"+_+"H"+f*a:"M"+c+","+v+"V"+_:a?"M"+v+","+f*a+"V"+c+"H"+_+"V"+f*a:"M"+v+","+c+"H"+_),w.attr("opacity",1).attr("transform",(function(t){return l(b(t)+c)})),A.attr(s+"2",f*o),S.attr(s,f*g).text(p),m.filter(Ct).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===wt?"start":t===Tt?"end":"middle"),m.each((function(){this.__axis=b}))}return h.scale=function(t){return arguments.length?(n=t,h):n},h.ticks=function(){return e=Array.from(arguments),h},h.tickArguments=function(t){return arguments.length?(e=null==t?[]:Array.from(t),h):e.slice()},h.tickValues=function(t){return arguments.length?(r=null==t?null:Array.from(t),h):r&&r.slice()},h.tickFormat=function(t){return arguments.length?(i=t,h):i},h.tickSize=function(t){return arguments.length?(o=a=+t,h):o},h.tickSizeInner=function(t){return arguments.length?(o=+t,h):o},h.tickSizeOuter=function(t){return arguments.length?(a=+t,h):a},h.tickPadding=function(t){return arguments.length?(u=+t,h):u},h.offset=function(t){return arguments.length?(c=+t,h):c},h}var zt={value:()=>{}};function $t(){for(var t,n=0,e=arguments.length,r={};n=0&&(n=t.slice(e+1),t=t.slice(0,e)),t&&!r.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))),a=-1,u=o.length;if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++a0)for(var e,r,i=new Array(e),o=0;o=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),Ut.hasOwnProperty(n)?{space:Ut[n],local:t}:t}function Ot(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===qt&&n.documentElement.namespaceURI===qt?n.createElement(t):n.createElementNS(e,t)}}function Bt(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Yt(t){var n=It(t);return(n.local?Bt:Ot)(n)}function Lt(){}function jt(t){return null==t?Lt:function(){return this.querySelector(t)}}function Ht(t){return null==t?[]:Array.isArray(t)?t:Array.from(t)}function Xt(){return[]}function Gt(t){return null==t?Xt:function(){return this.querySelectorAll(t)}}function Vt(t){return function(){return this.matches(t)}}function Wt(t){return function(n){return n.matches(t)}}var Zt=Array.prototype.find;function Kt(){return this.firstElementChild}var Qt=Array.prototype.filter;function Jt(){return Array.from(this.children)}function tn(t){return new Array(t.length)}function nn(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function en(t,n,e,r,i,o){for(var a,u=0,c=n.length,f=o.length;un?1:t>=n?0:NaN}function cn(t){return function(){this.removeAttribute(t)}}function fn(t){return function(){this.removeAttributeNS(t.space,t.local)}}function sn(t,n){return function(){this.setAttribute(t,n)}}function ln(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function hn(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function dn(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function pn(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function gn(t){return function(){this.style.removeProperty(t)}}function yn(t,n,e){return function(){this.style.setProperty(t,n,e)}}function vn(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function _n(t,n){return t.style.getPropertyValue(n)||pn(t).getComputedStyle(t,null).getPropertyValue(n)}function bn(t){return function(){delete this[t]}}function mn(t,n){return function(){this[t]=n}}function xn(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function wn(t){return t.trim().split(/^|\s+/)}function Mn(t){return t.classList||new Tn(t)}function Tn(t){this._node=t,this._names=wn(t.getAttribute("class")||"")}function An(t,n){for(var e=Mn(t),r=-1,i=n.length;++r=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var Gn=[null];function Vn(t,n){this._groups=t,this._parents=n}function Wn(){return new Vn([[document.documentElement]],Gn)}function Zn(t){return"string"==typeof t?new Vn([[document.querySelector(t)]],[document.documentElement]):new Vn([[t]],Gn)}Vn.prototype=Wn.prototype={constructor:Vn,select:function(t){"function"!=typeof t&&(t=jt(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i=m&&(m=b+1);!(_=y[m])&&++m=0;)(r=i[o])&&(a&&4^r.compareDocumentPosition(a)&&a.parentNode.insertBefore(r,a),a=r);return this},sort:function(t){function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}t||(t=un);for(var e=this._groups,r=e.length,i=new Array(r),o=0;o1?this.each((null==n?gn:"function"==typeof n?vn:yn)(t,n,null==e?"":e)):_n(this.node(),t)},property:function(t,n){return arguments.length>1?this.each((null==n?bn:"function"==typeof n?xn:mn)(t,n)):this.node()[t]},classed:function(t,n){var e=wn(t+"");if(arguments.length<2){for(var r=Mn(this.node()),i=-1,o=e.length;++i=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}}))}(t+""),a=o.length;if(!(arguments.length<2)){for(u=n?Ln:Yn,r=0;r()=>t;function fe(t,{sourceEvent:n,subject:e,target:r,identifier:i,active:o,x:a,y:u,dx:c,dy:f,dispatch:s}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:n,enumerable:!0,configurable:!0},subject:{value:e,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:i,enumerable:!0,configurable:!0},active:{value:o,enumerable:!0,configurable:!0},x:{value:a,enumerable:!0,configurable:!0},y:{value:u,enumerable:!0,configurable:!0},dx:{value:c,enumerable:!0,configurable:!0},dy:{value:f,enumerable:!0,configurable:!0},_:{value:s}})}function se(t){return!t.ctrlKey&&!t.button}function le(){return this.parentNode}function he(t,n){return null==n?{x:t.x,y:t.y}:n}function de(){return navigator.maxTouchPoints||"ontouchstart"in this}function pe(t,n,e){t.prototype=n.prototype=e,e.constructor=t}function ge(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[r];return e}function ye(){}fe.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};var ve=.7,_e=1/ve,be="\\s*([+-]?\\d+)\\s*",me="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",xe="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",we=/^#([0-9a-f]{3,8})$/,Me=new RegExp(`^rgb\\(${be},${be},${be}\\)$`),Te=new RegExp(`^rgb\\(${xe},${xe},${xe}\\)$`),Ae=new RegExp(`^rgba\\(${be},${be},${be},${me}\\)$`),Se=new RegExp(`^rgba\\(${xe},${xe},${xe},${me}\\)$`),Ee=new RegExp(`^hsl\\(${me},${xe},${xe}\\)$`),Ne=new RegExp(`^hsla\\(${me},${xe},${xe},${me}\\)$`),ke={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function Ce(){return this.rgb().formatHex()}function Pe(){return this.rgb().formatRgb()}function ze(t){var n,e;return t=(t+"").trim().toLowerCase(),(n=we.exec(t))?(e=n[1].length,n=parseInt(n[1],16),6===e?$e(n):3===e?new qe(n>>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1):8===e?De(n>>24&255,n>>16&255,n>>8&255,(255&n)/255):4===e?De(n>>12&15|n>>8&240,n>>8&15|n>>4&240,n>>4&15|240&n,((15&n)<<4|15&n)/255):null):(n=Me.exec(t))?new qe(n[1],n[2],n[3],1):(n=Te.exec(t))?new qe(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=Ae.exec(t))?De(n[1],n[2],n[3],n[4]):(n=Se.exec(t))?De(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=Ee.exec(t))?Le(n[1],n[2]/100,n[3]/100,1):(n=Ne.exec(t))?Le(n[1],n[2]/100,n[3]/100,n[4]):ke.hasOwnProperty(t)?$e(ke[t]):"transparent"===t?new qe(NaN,NaN,NaN,0):null}function $e(t){return new qe(t>>16&255,t>>8&255,255&t,1)}function De(t,n,e,r){return r<=0&&(t=n=e=NaN),new qe(t,n,e,r)}function Re(t){return t instanceof ye||(t=ze(t)),t?new qe((t=t.rgb()).r,t.g,t.b,t.opacity):new qe}function Fe(t,n,e,r){return 1===arguments.length?Re(t):new qe(t,n,e,null==r?1:r)}function qe(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function Ue(){return`#${Ye(this.r)}${Ye(this.g)}${Ye(this.b)}`}function Ie(){const t=Oe(this.opacity);return`${1===t?"rgb(":"rgba("}${Be(this.r)}, ${Be(this.g)}, ${Be(this.b)}${1===t?")":`, ${t})`}`}function Oe(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function Be(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function Ye(t){return((t=Be(t))<16?"0":"")+t.toString(16)}function Le(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new Xe(t,n,e,r)}function je(t){if(t instanceof Xe)return new Xe(t.h,t.s,t.l,t.opacity);if(t instanceof ye||(t=ze(t)),!t)return new Xe;if(t instanceof Xe)return t;var n=(t=t.rgb()).r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),a=NaN,u=o-i,c=(o+i)/2;return u?(a=n===o?(e-r)/u+6*(e0&&c<1?0:a,new Xe(a,u,c,t.opacity)}function He(t,n,e,r){return 1===arguments.length?je(t):new Xe(t,n,e,null==r?1:r)}function Xe(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function Ge(t){return(t=(t||0)%360)<0?t+360:t}function Ve(t){return Math.max(0,Math.min(1,t||0))}function We(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}pe(ye,ze,{copy(t){return Object.assign(new this.constructor,this,t)},displayable(){return this.rgb().displayable()},hex:Ce,formatHex:Ce,formatHex8:function(){return this.rgb().formatHex8()},formatHsl:function(){return je(this).formatHsl()},formatRgb:Pe,toString:Pe}),pe(qe,Fe,ge(ye,{brighter(t){return t=null==t?_e:Math.pow(_e,t),new qe(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=null==t?ve:Math.pow(ve,t),new qe(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new qe(Be(this.r),Be(this.g),Be(this.b),Oe(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:Ue,formatHex:Ue,formatHex8:function(){return`#${Ye(this.r)}${Ye(this.g)}${Ye(this.b)}${Ye(255*(isNaN(this.opacity)?1:this.opacity))}`},formatRgb:Ie,toString:Ie})),pe(Xe,He,ge(ye,{brighter(t){return t=null==t?_e:Math.pow(_e,t),new Xe(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=null==t?ve:Math.pow(ve,t),new Xe(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+360*(this.h<0),n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new qe(We(t>=240?t-240:t+120,i,r),We(t,i,r),We(t<120?t+240:t-120,i,r),this.opacity)},clamp(){return new Xe(Ge(this.h),Ve(this.s),Ve(this.l),Oe(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=Oe(this.opacity);return`${1===t?"hsl(":"hsla("}${Ge(this.h)}, ${100*Ve(this.s)}%, ${100*Ve(this.l)}%${1===t?")":`, ${t})`}`}}));const Ze=Math.PI/180,Ke=180/Math.PI,Qe=.96422,Je=1,tr=.82521,nr=4/29,er=6/29,rr=3*er*er,ir=er*er*er;function or(t){if(t instanceof ur)return new ur(t.l,t.a,t.b,t.opacity);if(t instanceof pr)return gr(t);t instanceof qe||(t=Re(t));var n,e,r=lr(t.r),i=lr(t.g),o=lr(t.b),a=cr((.2225045*r+.7168786*i+.0606169*o)/Je);return r===i&&i===o?n=e=a:(n=cr((.4360747*r+.3850649*i+.1430804*o)/Qe),e=cr((.0139322*r+.0971045*i+.7141733*o)/tr)),new ur(116*a-16,500*(n-a),200*(a-e),t.opacity)}function ar(t,n,e,r){return 1===arguments.length?or(t):new ur(t,n,e,null==r?1:r)}function ur(t,n,e,r){this.l=+t,this.a=+n,this.b=+e,this.opacity=+r}function cr(t){return t>ir?Math.pow(t,1/3):t/rr+nr}function fr(t){return t>er?t*t*t:rr*(t-nr)}function sr(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function lr(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function hr(t){if(t instanceof pr)return new pr(t.h,t.c,t.l,t.opacity);if(t instanceof ur||(t=or(t)),0===t.a&&0===t.b)return new pr(NaN,0=1?(e=1,n-1):Math.floor(e*n),i=t[r],o=t[r+1],a=r>0?t[r-1]:2*i-o,u=r()=>t;function Cr(t,n){return function(e){return t+e*n}}function Pr(t,n){var e=n-t;return e?Cr(t,e>180||e<-180?e-360*Math.round(e/360):e):kr(isNaN(t)?n:t)}function zr(t){return 1==(t=+t)?$r:function(n,e){return e-n?function(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}(n,e,t):kr(isNaN(n)?e:n)}}function $r(t,n){var e=n-t;return e?Cr(t,e):kr(isNaN(t)?n:t)}var Dr=function t(n){var e=zr(n);function r(t,n){var r=e((t=Fe(t)).r,(n=Fe(n)).r),i=e(t.g,n.g),o=e(t.b,n.b),a=$r(t.opacity,n.opacity);return function(n){return t.r=r(n),t.g=i(n),t.b=o(n),t.opacity=a(n),t+""}}return r.gamma=t,r}(1);function Rr(t){return function(n){var e,r,i=n.length,o=new Array(i),a=new Array(i),u=new Array(i);for(e=0;eo&&(i=n.slice(o,i),u[a]?u[a]+=i:u[++a]=i),(e=e[0])===(r=r[0])?u[a]?u[a]+=r:u[++a]=r:(u[++a]=null,c.push({i:a,x:Yr(e,r)})),o=Hr.lastIndex;return o180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+"rotate(",null,r)-2,x:Yr(t,n)})):n&&e.push(i(e)+"rotate("+n+r)}(o.rotate,a.rotate,u,c),function(t,n,e,o){t!==n?o.push({i:e.push(i(e)+"skewX(",null,r)-2,x:Yr(t,n)}):n&&e.push(i(e)+"skewX("+n+r)}(o.skewX,a.skewX,u,c),function(t,n,e,r,o,a){if(t!==e||n!==r){var u=o.push(i(o)+"scale(",null,",",null,")");a.push({i:u-4,x:Yr(t,e)},{i:u-2,x:Yr(n,r)})}else 1===e&&1===r||o.push(i(o)+"scale("+e+","+r+")")}(o.scaleX,o.scaleY,a.scaleX,a.scaleY,u,c),o=a=null,function(t){for(var n,e=-1,r=c.length;++e=0&&n._call.call(void 0,t),n=n._next;--yi}function Ci(){xi=(mi=Mi.now())+wi,yi=vi=0;try{ki()}finally{yi=0,function(){var t,n,e=pi,r=1/0;for(;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:pi=n);gi=t,zi(r)}(),xi=0}}function Pi(){var t=Mi.now(),n=t-mi;n>bi&&(wi-=n,mi=t)}function zi(t){yi||(vi&&(vi=clearTimeout(vi)),t-xi>24?(t<1/0&&(vi=setTimeout(Ci,t-Mi.now()-wi)),_i&&(_i=clearInterval(_i))):(_i||(mi=Mi.now(),_i=setInterval(Pi,bi)),yi=1,Ti(Ci)))}function $i(t,n,e){var r=new Ei;return n=null==n?0:+n,r.restart((e=>{r.stop(),t(e+n)}),n,e),r}Ei.prototype=Ni.prototype={constructor:Ei,restart:function(t,n,e){if("function"!=typeof t)throw new TypeError("callback is not a function");e=(null==e?Ai():+e)+(null==n?0:+n),this._next||gi===this||(gi?gi._next=this:pi=this,gi=this),this._call=t,this._time=e,zi()},stop:function(){this._call&&(this._call=null,this._time=1/0,zi())}};var Di=$t("start","end","cancel","interrupt"),Ri=[],Fi=0,qi=1,Ui=2,Ii=3,Oi=4,Bi=5,Yi=6;function Li(t,n,e,r,i,o){var a=t.__transition;if(a){if(e in a)return}else t.__transition={};!function(t,n,e){var r,i=t.__transition;function o(t){e.state=qi,e.timer.restart(a,e.delay,e.time),e.delay<=t&&a(t-e.delay)}function a(o){var f,s,l,h;if(e.state!==qi)return c();for(f in i)if((h=i[f]).name===e.name){if(h.state===Ii)return $i(a);h.state===Oi?(h.state=Yi,h.timer.stop(),h.on.call("interrupt",t,t.__data__,h.index,h.group),delete i[f]):+fFi)throw new Error("too late; already scheduled");return e}function Hi(t,n){var e=Xi(t,n);if(e.state>Ii)throw new Error("too late; already running");return e}function Xi(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("transition not found");return e}function Gi(t,n){var e,r,i,o=t.__transition,a=!0;if(o){for(i in n=null==n?null:n+"",o)(e=o[i]).name===n?(r=e.state>Ui&&e.state=0&&(t=t.slice(0,n)),!t||"start"===t}))}(n)?ji:Hi;return function(){var a=o(this,t),u=a.on;u!==r&&(i=(r=u).copy()).on(n,e),a.on=i}}(e,t,n))},attr:function(t,n){var e=It(t),r="transform"===e?ni:Ki;return this.attrTween(t,"function"==typeof n?(e.local?ro:eo)(e,r,Zi(this,"attr."+t,n)):null==n?(e.local?Ji:Qi)(e):(e.local?no:to)(e,r,n))},attrTween:function(t,n){var e="attr."+t;if(arguments.length<2)return(e=this.tween(e))&&e._value;if(null==n)return this.tween(e,null);if("function"!=typeof n)throw new Error;var r=It(t);return this.tween(e,(r.local?io:oo)(r,n))},style:function(t,n,e){var r="transform"==(t+="")?ti:Ki;return null==n?this.styleTween(t,function(t,n){var e,r,i;return function(){var o=_n(this,t),a=(this.style.removeProperty(t),_n(this,t));return o===a?null:o===e&&a===r?i:i=n(e=o,r=a)}}(t,r)).on("end.style."+t,lo(t)):"function"==typeof n?this.styleTween(t,function(t,n,e){var r,i,o;return function(){var a=_n(this,t),u=e(this),c=u+"";return null==u&&(this.style.removeProperty(t),c=u=_n(this,t)),a===c?null:a===r&&c===i?o:(i=c,o=n(r=a,u))}}(t,r,Zi(this,"style."+t,n))).each(function(t,n){var e,r,i,o,a="style."+n,u="end."+a;return function(){var c=Hi(this,t),f=c.on,s=null==c.value[a]?o||(o=lo(n)):void 0;f===e&&i===s||(r=(e=f).copy()).on(u,i=s),c.on=r}}(this._id,t)):this.styleTween(t,function(t,n,e){var r,i,o=e+"";return function(){var a=_n(this,t);return a===o?null:a===r?i:i=n(r=a,e)}}(t,r,n),e).on("end.style."+t,null)},styleTween:function(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,function(t,n,e){var r,i;function o(){var o=n.apply(this,arguments);return o!==i&&(r=(i=o)&&function(t,n,e){return function(r){this.style.setProperty(t,n.call(this,r),e)}}(t,o,e)),r}return o._value=n,o}(t,n,null==e?"":e))},text:function(t){return this.tween("text","function"==typeof t?function(t){return function(){var n=t(this);this.textContent=null==n?"":n}}(Zi(this,"text",t)):function(t){return function(){this.textContent=t}}(null==t?"":t+""))},textTween:function(t){var n="text";if(arguments.length<1)return(n=this.tween(n))&&n._value;if(null==t)return this.tween(n,null);if("function"!=typeof t)throw new Error;return this.tween(n,function(t){var n,e;function r(){var r=t.apply(this,arguments);return r!==e&&(n=(e=r)&&function(t){return function(n){this.textContent=t.call(this,n)}}(r)),n}return r._value=t,r}(t))},remove:function(){return this.on("end.remove",function(t){return function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}}(this._id))},tween:function(t,n){var e=this._id;if(t+="",arguments.length<2){for(var r,i=Xi(this.node(),e).tween,o=0,a=i.length;o()=>t;function Qo(t,{sourceEvent:n,target:e,selection:r,mode:i,dispatch:o}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:n,enumerable:!0,configurable:!0},target:{value:e,enumerable:!0,configurable:!0},selection:{value:r,enumerable:!0,configurable:!0},mode:{value:i,enumerable:!0,configurable:!0},_:{value:o}})}function Jo(t){t.preventDefault(),t.stopImmediatePropagation()}var ta={name:"drag"},na={name:"space"},ea={name:"handle"},ra={name:"center"};const{abs:ia,max:oa,min:aa}=Math;function ua(t){return[+t[0],+t[1]]}function ca(t){return[ua(t[0]),ua(t[1])]}var fa={name:"x",handles:["w","e"].map(va),input:function(t,n){return null==t?null:[[+t[0],n[0][1]],[+t[1],n[1][1]]]},output:function(t){return t&&[t[0][0],t[1][0]]}},sa={name:"y",handles:["n","s"].map(va),input:function(t,n){return null==t?null:[[n[0][0],+t[0]],[n[1][0],+t[1]]]},output:function(t){return t&&[t[0][1],t[1][1]]}},la={name:"xy",handles:["n","w","e","s","nw","ne","sw","se"].map(va),input:function(t){return null==t?null:ca(t)},output:function(t){return t}},ha={overlay:"crosshair",selection:"move",n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},da={e:"w",w:"e",nw:"ne",ne:"nw",se:"sw",sw:"se"},pa={n:"s",s:"n",nw:"sw",ne:"se",se:"ne",sw:"nw"},ga={overlay:1,selection:1,n:null,e:1,s:null,w:-1,nw:-1,ne:1,se:1,sw:-1},ya={overlay:1,selection:1,n:-1,e:null,s:1,w:null,nw:-1,ne:-1,se:1,sw:1};function va(t){return{type:t}}function _a(t){return!t.ctrlKey&&!t.button}function ba(){var t=this.ownerSVGElement||this;return t.hasAttribute("viewBox")?[[(t=t.viewBox.baseVal).x,t.y],[t.x+t.width,t.y+t.height]]:[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]}function ma(){return navigator.maxTouchPoints||"ontouchstart"in this}function xa(t){for(;!t.__brush;)if(!(t=t.parentNode))return;return t.__brush}function wa(t){var n,e=ba,r=_a,i=ma,o=!0,a=$t("start","brush","end"),u=6;function c(n){var e=n.property("__brush",g).selectAll(".overlay").data([va("overlay")]);e.enter().append("rect").attr("class","overlay").attr("pointer-events","all").attr("cursor",ha.overlay).merge(e).each((function(){var t=xa(this).extent;Zn(this).attr("x",t[0][0]).attr("y",t[0][1]).attr("width",t[1][0]-t[0][0]).attr("height",t[1][1]-t[0][1])})),n.selectAll(".selection").data([va("selection")]).enter().append("rect").attr("class","selection").attr("cursor",ha.selection).attr("fill","#777").attr("fill-opacity",.3).attr("stroke","#fff").attr("shape-rendering","crispEdges");var r=n.selectAll(".handle").data(t.handles,(function(t){return t.type}));r.exit().remove(),r.enter().append("rect").attr("class",(function(t){return"handle handle--"+t.type})).attr("cursor",(function(t){return ha[t.type]})),n.each(f).attr("fill","none").attr("pointer-events","all").on("mousedown.brush",h).filter(i).on("touchstart.brush",h).on("touchmove.brush",d).on("touchend.brush touchcancel.brush",p).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function f(){var t=Zn(this),n=xa(this).selection;n?(t.selectAll(".selection").style("display",null).attr("x",n[0][0]).attr("y",n[0][1]).attr("width",n[1][0]-n[0][0]).attr("height",n[1][1]-n[0][1]),t.selectAll(".handle").style("display",null).attr("x",(function(t){return"e"===t.type[t.type.length-1]?n[1][0]-u/2:n[0][0]-u/2})).attr("y",(function(t){return"s"===t.type[0]?n[1][1]-u/2:n[0][1]-u/2})).attr("width",(function(t){return"n"===t.type||"s"===t.type?n[1][0]-n[0][0]+u:u})).attr("height",(function(t){return"e"===t.type||"w"===t.type?n[1][1]-n[0][1]+u:u}))):t.selectAll(".selection,.handle").style("display","none").attr("x",null).attr("y",null).attr("width",null).attr("height",null)}function s(t,n,e){var r=t.__brush.emitter;return!r||e&&r.clean?new l(t,n,e):r}function l(t,n,e){this.that=t,this.args=n,this.state=t.__brush,this.active=0,this.clean=e}function h(e){if((!n||e.touches)&&r.apply(this,arguments)){var i,a,u,c,l,h,d,p,g,y,v,_=this,b=e.target.__data__.type,m="selection"===(o&&e.metaKey?b="overlay":b)?ta:o&&e.altKey?ra:ea,x=t===sa?null:ga[b],w=t===fa?null:ya[b],M=xa(_),T=M.extent,A=M.selection,S=T[0][0],E=T[0][1],N=T[1][0],k=T[1][1],C=0,P=0,z=x&&w&&o&&e.shiftKey,$=Array.from(e.touches||[e],(t=>{const n=t.identifier;return(t=ne(t,_)).point0=t.slice(),t.identifier=n,t}));Gi(_);var D=s(_,arguments,!0).beforestart();if("overlay"===b){A&&(g=!0);const n=[$[0],$[1]||$[0]];M.selection=A=[[i=t===sa?S:aa(n[0][0],n[1][0]),u=t===fa?E:aa(n[0][1],n[1][1])],[l=t===sa?N:oa(n[0][0],n[1][0]),d=t===fa?k:oa(n[0][1],n[1][1])]],$.length>1&&I(e)}else i=A[0][0],u=A[0][1],l=A[1][0],d=A[1][1];a=i,c=u,h=l,p=d;var R=Zn(_).attr("pointer-events","none"),F=R.selectAll(".overlay").attr("cursor",ha[b]);if(e.touches)D.moved=U,D.ended=O;else{var q=Zn(e.view).on("mousemove.brush",U,!0).on("mouseup.brush",O,!0);o&&q.on("keydown.brush",(function(t){switch(t.keyCode){case 16:z=x&&w;break;case 18:m===ea&&(x&&(l=h-C*x,i=a+C*x),w&&(d=p-P*w,u=c+P*w),m=ra,I(t));break;case 32:m!==ea&&m!==ra||(x<0?l=h-C:x>0&&(i=a-C),w<0?d=p-P:w>0&&(u=c-P),m=na,F.attr("cursor",ha.selection),I(t));break;default:return}Jo(t)}),!0).on("keyup.brush",(function(t){switch(t.keyCode){case 16:z&&(y=v=z=!1,I(t));break;case 18:m===ra&&(x<0?l=h:x>0&&(i=a),w<0?d=p:w>0&&(u=c),m=ea,I(t));break;case 32:m===na&&(t.altKey?(x&&(l=h-C*x,i=a+C*x),w&&(d=p-P*w,u=c+P*w),m=ra):(x<0?l=h:x>0&&(i=a),w<0?d=p:w>0&&(u=c),m=ea),F.attr("cursor",ha[b]),I(t));break;default:return}Jo(t)}),!0),ae(e.view)}f.call(_),D.start(e,m.name)}function U(t){for(const n of t.changedTouches||[t])for(const t of $)t.identifier===n.identifier&&(t.cur=ne(n,_));if(z&&!y&&!v&&1===$.length){const t=$[0];ia(t.cur[0]-t[0])>ia(t.cur[1]-t[1])?v=!0:y=!0}for(const t of $)t.cur&&(t[0]=t.cur[0],t[1]=t.cur[1]);g=!0,Jo(t),I(t)}function I(t){const n=$[0],e=n.point0;var r;switch(C=n[0]-e[0],P=n[1]-e[1],m){case na:case ta:x&&(C=oa(S-i,aa(N-l,C)),a=i+C,h=l+C),w&&(P=oa(E-u,aa(k-d,P)),c=u+P,p=d+P);break;case ea:$[1]?(x&&(a=oa(S,aa(N,$[0][0])),h=oa(S,aa(N,$[1][0])),x=1),w&&(c=oa(E,aa(k,$[0][1])),p=oa(E,aa(k,$[1][1])),w=1)):(x<0?(C=oa(S-i,aa(N-i,C)),a=i+C,h=l):x>0&&(C=oa(S-l,aa(N-l,C)),a=i,h=l+C),w<0?(P=oa(E-u,aa(k-u,P)),c=u+P,p=d):w>0&&(P=oa(E-d,aa(k-d,P)),c=u,p=d+P));break;case ra:x&&(a=oa(S,aa(N,i-C*x)),h=oa(S,aa(N,l+C*x))),w&&(c=oa(E,aa(k,u-P*w)),p=oa(E,aa(k,d+P*w)))}ht+e))}function za(t,n){var e=0,r=null,i=null,o=null;function a(a){var u,c=a.length,f=new Array(c),s=Pa(0,c),l=new Array(c*c),h=new Array(c),d=0;a=Float64Array.from({length:c*c},n?(t,n)=>a[n%c][n/c|0]:(t,n)=>a[n/c|0][n%c]);for(let n=0;nr(f[t],f[n])));for(const e of s){const r=n;if(t){const t=Pa(1+~c,c).filter((t=>t<0?a[~t*c+e]:a[e*c+t]));i&&t.sort(((t,n)=>i(t<0?-a[~t*c+e]:a[e*c+t],n<0?-a[~n*c+e]:a[e*c+n])));for(const r of t)if(r<0){(l[~r*c+e]||(l[~r*c+e]={source:null,target:null})).target={index:e,startAngle:n,endAngle:n+=a[~r*c+e]*d,value:a[~r*c+e]}}else{(l[e*c+r]||(l[e*c+r]={source:null,target:null})).source={index:e,startAngle:n,endAngle:n+=a[e*c+r]*d,value:a[e*c+r]}}h[e]={index:e,startAngle:r,endAngle:n,value:f[e]}}else{const t=Pa(0,c).filter((t=>a[e*c+t]||a[t*c+e]));i&&t.sort(((t,n)=>i(a[e*c+t],a[e*c+n])));for(const r of t){let t;if(e=0))throw new Error(`invalid digits: ${t}`);if(n>15)return qa;const e=10**n;return function(t){this._+=t[0];for(let n=1,r=t.length;nRa)if(Math.abs(s*u-c*f)>Ra&&i){let h=e-o,d=r-a,p=u*u+c*c,g=h*h+d*d,y=Math.sqrt(p),v=Math.sqrt(l),_=i*Math.tan(($a-Math.acos((p+l-g)/(2*y*v)))/2),b=_/v,m=_/y;Math.abs(b-1)>Ra&&this._append`L${t+b*f},${n+b*s}`,this._append`A${i},${i},0,0,${+(s*h>f*d)},${this._x1=t+m*u},${this._y1=n+m*c}`}else this._append`L${this._x1=t},${this._y1=n}`;else;}arc(t,n,e,r,i,o){if(t=+t,n=+n,o=!!o,(e=+e)<0)throw new Error(`negative radius: ${e}`);let a=e*Math.cos(r),u=e*Math.sin(r),c=t+a,f=n+u,s=1^o,l=o?r-i:i-r;null===this._x1?this._append`M${c},${f}`:(Math.abs(this._x1-c)>Ra||Math.abs(this._y1-f)>Ra)&&this._append`L${c},${f}`,e&&(l<0&&(l=l%Da+Da),l>Fa?this._append`A${e},${e},0,1,${s},${t-a},${n-u}A${e},${e},0,1,${s},${this._x1=c},${this._y1=f}`:l>Ra&&this._append`A${e},${e},0,${+(l>=$a)},${s},${this._x1=t+e*Math.cos(i)},${this._y1=n+e*Math.sin(i)}`)}rect(t,n,e,r){this._append`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}h${e=+e}v${+r}h${-e}Z`}toString(){return this._}};function Ia(){return new Ua}Ia.prototype=Ua.prototype;var Oa=Array.prototype.slice;function Ba(t){return function(){return t}}function Ya(t){return t.source}function La(t){return t.target}function ja(t){return t.radius}function Ha(t){return t.startAngle}function Xa(t){return t.endAngle}function Ga(){return 0}function Va(){return 10}function Wa(t){var n=Ya,e=La,r=ja,i=ja,o=Ha,a=Xa,u=Ga,c=null;function f(){var f,s=n.apply(this,arguments),l=e.apply(this,arguments),h=u.apply(this,arguments)/2,d=Oa.call(arguments),p=+r.apply(this,(d[0]=s,d)),g=o.apply(this,d)-Ea,y=a.apply(this,d)-Ea,v=+i.apply(this,(d[0]=l,d)),_=o.apply(this,d)-Ea,b=a.apply(this,d)-Ea;if(c||(c=f=Ia()),h>Ca&&(Ma(y-g)>2*h+Ca?y>g?(g+=h,y-=h):(g-=h,y+=h):g=y=(g+y)/2,Ma(b-_)>2*h+Ca?b>_?(_+=h,b-=h):(_-=h,b+=h):_=b=(_+b)/2),c.moveTo(p*Ta(g),p*Aa(g)),c.arc(0,0,p,g,y),g!==_||y!==b)if(t){var m=v-+t.apply(this,arguments),x=(_+b)/2;c.quadraticCurveTo(0,0,m*Ta(_),m*Aa(_)),c.lineTo(v*Ta(x),v*Aa(x)),c.lineTo(m*Ta(b),m*Aa(b))}else c.quadraticCurveTo(0,0,v*Ta(_),v*Aa(_)),c.arc(0,0,v,_,b);if(c.quadraticCurveTo(0,0,p*Ta(g),p*Aa(g)),c.closePath(),f)return c=null,f+""||null}return t&&(f.headRadius=function(n){return arguments.length?(t="function"==typeof n?n:Ba(+n),f):t}),f.radius=function(t){return arguments.length?(r=i="function"==typeof t?t:Ba(+t),f):r},f.sourceRadius=function(t){return arguments.length?(r="function"==typeof t?t:Ba(+t),f):r},f.targetRadius=function(t){return arguments.length?(i="function"==typeof t?t:Ba(+t),f):i},f.startAngle=function(t){return arguments.length?(o="function"==typeof t?t:Ba(+t),f):o},f.endAngle=function(t){return arguments.length?(a="function"==typeof t?t:Ba(+t),f):a},f.padAngle=function(t){return arguments.length?(u="function"==typeof t?t:Ba(+t),f):u},f.source=function(t){return arguments.length?(n=t,f):n},f.target=function(t){return arguments.length?(e=t,f):e},f.context=function(t){return arguments.length?(c=null==t?null:t,f):c},f}var Za=Array.prototype.slice;function Ka(t,n){return t-n}var Qa=t=>()=>t;function Ja(t,n){for(var e,r=-1,i=n.length;++rr!=d>r&&e<(h-f)*(r-s)/(d-s)+f&&(i=-i)}return i}function nu(t,n,e){var r,i,o,a;return function(t,n,e){return(n[0]-t[0])*(e[1]-t[1])==(e[0]-t[0])*(n[1]-t[1])}(t,n,e)&&(i=t[r=+(t[0]===n[0])],o=e[r],a=n[r],i<=o&&o<=a||a<=o&&o<=i)}function eu(){}var ru=[[],[[[1,1.5],[.5,1]]],[[[1.5,1],[1,1.5]]],[[[1.5,1],[.5,1]]],[[[1,.5],[1.5,1]]],[[[1,1.5],[.5,1]],[[1,.5],[1.5,1]]],[[[1,.5],[1,1.5]]],[[[1,.5],[.5,1]]],[[[.5,1],[1,.5]]],[[[1,1.5],[1,.5]]],[[[.5,1],[1,.5]],[[1.5,1],[1,1.5]]],[[[1.5,1],[1,.5]]],[[[.5,1],[1.5,1]]],[[[1,1.5],[1.5,1]]],[[[.5,1],[1,1.5]]],[]];function iu(){var t=1,n=1,e=K,r=u;function i(t){var n=e(t);if(Array.isArray(n))n=n.slice().sort(Ka);else{const e=M(t,ou);for(n=G(...Z(e[0],e[1],n),n);n[n.length-1]>=e[1];)n.pop();for(;n[1]o(t,n)))}function o(e,i){const o=null==i?NaN:+i;if(isNaN(o))throw new Error(`invalid value: ${i}`);var u=[],c=[];return function(e,r,i){var o,u,c,f,s,l,h=new Array,d=new Array;o=u=-1,f=au(e[0],r),ru[f<<1].forEach(p);for(;++o=r,ru[s<<2].forEach(p);for(;++o0?u.push([t]):c.push(t)})),c.forEach((function(t){for(var n,e=0,r=u.length;e0&&o0&&a=0&&o>=0))throw new Error("invalid size");return t=r,n=o,i},i.thresholds=function(t){return arguments.length?(e="function"==typeof t?t:Array.isArray(t)?Qa(Za.call(t)):Qa(t),i):e},i.smooth=function(t){return arguments.length?(r=t?u:eu,i):r===u},i}function ou(t){return isFinite(t)?t:NaN}function au(t,n){return null!=t&&+t>=n}function uu(t){return null==t||isNaN(t=+t)?-1/0:t}function cu(t,n,e,r){const i=r-n,o=e-n,a=isFinite(i)||isFinite(o)?i/o:Math.sign(i)/Math.sign(o);return isNaN(a)?t:t+a-.5}function fu(t){return t[0]}function su(t){return t[1]}function lu(){return 1}const hu=134217729,du=33306690738754706e-32;function pu(t,n,e,r,i){let o,a,u,c,f=n[0],s=r[0],l=0,h=0;s>f==s>-f?(o=f,f=n[++l]):(o=s,s=r[++h]);let d=0;if(lf==s>-f?(a=f+o,u=o-(a-f),f=n[++l]):(a=s+o,u=o-(a-s),s=r[++h]),o=a,0!==u&&(i[d++]=u);lf==s>-f?(a=o+f,c=a-o,u=o-(a-c)+(f-c),f=n[++l]):(a=o+s,c=a-o,u=o-(a-c)+(s-c),s=r[++h]),o=a,0!==u&&(i[d++]=u);for(;l=33306690738754716e-32*f?c:-function(t,n,e,r,i,o,a){let u,c,f,s,l,h,d,p,g,y,v,_,b,m,x,w,M,T;const A=t-i,S=e-i,E=n-o,N=r-o;m=A*N,h=hu*A,d=h-(h-A),p=A-d,h=hu*N,g=h-(h-N),y=N-g,x=p*y-(m-d*g-p*g-d*y),w=E*S,h=hu*E,d=h-(h-E),p=E-d,h=hu*S,g=h-(h-S),y=S-g,M=p*y-(w-d*g-p*g-d*y),v=x-M,l=x-v,_u[0]=x-(v+l)+(l-M),_=m+v,l=_-m,b=m-(_-l)+(v-l),v=b-w,l=b-v,_u[1]=b-(v+l)+(l-w),T=_+v,l=T-_,_u[2]=_-(T-l)+(v-l),_u[3]=T;let k=function(t,n){let e=n[0];for(let r=1;r=C||-k>=C)return k;if(l=t-A,u=t-(A+l)+(l-i),l=e-S,f=e-(S+l)+(l-i),l=n-E,c=n-(E+l)+(l-o),l=r-N,s=r-(N+l)+(l-o),0===u&&0===c&&0===f&&0===s)return k;if(C=vu*a+du*Math.abs(k),k+=A*s+N*u-(E*f+S*c),k>=C||-k>=C)return k;m=u*N,h=hu*u,d=h-(h-u),p=u-d,h=hu*N,g=h-(h-N),y=N-g,x=p*y-(m-d*g-p*g-d*y),w=c*S,h=hu*c,d=h-(h-c),p=c-d,h=hu*S,g=h-(h-S),y=S-g,M=p*y-(w-d*g-p*g-d*y),v=x-M,l=x-v,wu[0]=x-(v+l)+(l-M),_=m+v,l=_-m,b=m-(_-l)+(v-l),v=b-w,l=b-v,wu[1]=b-(v+l)+(l-w),T=_+v,l=T-_,wu[2]=_-(T-l)+(v-l),wu[3]=T;const P=pu(4,_u,4,wu,bu);m=A*s,h=hu*A,d=h-(h-A),p=A-d,h=hu*s,g=h-(h-s),y=s-g,x=p*y-(m-d*g-p*g-d*y),w=E*f,h=hu*E,d=h-(h-E),p=E-d,h=hu*f,g=h-(h-f),y=f-g,M=p*y-(w-d*g-p*g-d*y),v=x-M,l=x-v,wu[0]=x-(v+l)+(l-M),_=m+v,l=_-m,b=m-(_-l)+(v-l),v=b-w,l=b-v,wu[1]=b-(v+l)+(l-w),T=_+v,l=T-_,wu[2]=_-(T-l)+(v-l),wu[3]=T;const z=pu(P,bu,4,wu,mu);m=u*s,h=hu*u,d=h-(h-u),p=u-d,h=hu*s,g=h-(h-s),y=s-g,x=p*y-(m-d*g-p*g-d*y),w=c*f,h=hu*c,d=h-(h-c),p=c-d,h=hu*f,g=h-(h-f),y=f-g,M=p*y-(w-d*g-p*g-d*y),v=x-M,l=x-v,wu[0]=x-(v+l)+(l-M),_=m+v,l=_-m,b=m-(_-l)+(v-l),v=b-w,l=b-v,wu[1]=b-(v+l)+(l-w),T=_+v,l=T-_,wu[2]=_-(T-l)+(v-l),wu[3]=T;const $=pu(z,mu,4,wu,xu);return xu[$-1]}(t,n,e,r,i,o,f)}const Tu=Math.pow(2,-52),Au=new Uint32Array(512);class Su{static from(t,n=zu,e=$u){const r=t.length,i=new Float64Array(2*r);for(let o=0;o>1;if(n>0&&"number"!=typeof t[0])throw new Error("Expected coords to contain numbers.");this.coords=t;const e=Math.max(2*n-5,0);this._triangles=new Uint32Array(3*e),this._halfedges=new Int32Array(3*e),this._hashSize=Math.ceil(Math.sqrt(n)),this._hullPrev=new Uint32Array(n),this._hullNext=new Uint32Array(n),this._hullTri=new Uint32Array(n),this._hullHash=new Int32Array(this._hashSize).fill(-1),this._ids=new Uint32Array(n),this._dists=new Float64Array(n),this.update()}update(){const{coords:t,_hullPrev:n,_hullNext:e,_hullTri:r,_hullHash:i}=this,o=t.length>>1;let a=1/0,u=1/0,c=-1/0,f=-1/0;for(let n=0;nc&&(c=e),r>f&&(f=r),this._ids[n]=n}const s=(a+c)/2,l=(u+f)/2;let h,d,p,g=1/0;for(let n=0;n0&&(d=n,g=e)}let _=t[2*d],b=t[2*d+1],m=1/0;for(let n=0;nr&&(n[e++]=i,r=this._dists[i])}return this.hull=n.subarray(0,e),this.triangles=new Uint32Array(0),void(this.halfedges=new Uint32Array(0))}if(Mu(y,v,_,b,x,w)<0){const t=d,n=_,e=b;d=p,_=x,b=w,p=t,x=n,w=e}const M=function(t,n,e,r,i,o){const a=e-t,u=r-n,c=i-t,f=o-n,s=a*a+u*u,l=c*c+f*f,h=.5/(a*f-u*c),d=t+(f*s-u*l)*h,p=n+(a*l-c*s)*h;return{x:d,y:p}}(y,v,_,b,x,w);this._cx=M.x,this._cy=M.y;for(let n=0;n0&&Math.abs(f-o)<=Tu&&Math.abs(s-a)<=Tu)continue;if(o=f,a=s,c===h||c===d||c===p)continue;let l=0;for(let t=0,n=this._hashKey(f,s);t=0;)if(y=g,y===l){y=-1;break}if(-1===y)continue;let v=this._addTriangle(y,c,e[y],-1,-1,r[y]);r[c]=this._legalize(v+2),r[y]=v,T++;let _=e[y];for(;g=e[_],Mu(f,s,t[2*_],t[2*_+1],t[2*g],t[2*g+1])<0;)v=this._addTriangle(_,c,g,r[c],-1,r[_]),r[c]=this._legalize(v+2),e[_]=_,T--,_=g;if(y===l)for(;g=n[y],Mu(f,s,t[2*g],t[2*g+1],t[2*y],t[2*y+1])<0;)v=this._addTriangle(g,c,y,-1,r[y],r[g]),this._legalize(v+2),r[g]=v,e[y]=y,T--,y=g;this._hullStart=n[c]=y,e[y]=n[_]=c,e[c]=_,i[this._hashKey(f,s)]=c,i[this._hashKey(t[2*y],t[2*y+1])]=y}this.hull=new Uint32Array(T);for(let t=0,n=this._hullStart;t0?3-e:1+e)/4}(t-this._cx,n-this._cy)*this._hashSize)%this._hashSize}_legalize(t){const{_triangles:n,_halfedges:e,coords:r}=this;let i=0,o=0;for(;;){const a=e[t],u=t-t%3;if(o=u+(t+2)%3,-1===a){if(0===i)break;t=Au[--i];continue}const c=a-a%3,f=u+(t+1)%3,s=c+(a+2)%3,l=n[o],h=n[t],d=n[f],p=n[s];if(Nu(r[2*l],r[2*l+1],r[2*h],r[2*h+1],r[2*d],r[2*d+1],r[2*p],r[2*p+1])){n[t]=p,n[a]=l;const r=e[s];if(-1===r){let n=this._hullStart;do{if(this._hullTri[n]===s){this._hullTri[n]=t;break}n=this._hullPrev[n]}while(n!==this._hullStart)}this._link(t,r),this._link(a,e[o]),this._link(o,s);const u=c+(a+1)%3;i=e&&n[t[a]]>o;)t[a+1]=t[a--];t[a+1]=r}else{let i=e+1,o=r;Pu(t,e+r>>1,i),n[t[e]]>n[t[r]]&&Pu(t,e,r),n[t[i]]>n[t[r]]&&Pu(t,i,r),n[t[e]]>n[t[i]]&&Pu(t,e,i);const a=t[i],u=n[a];for(;;){do{i++}while(n[t[i]]u);if(o=o-e?(Cu(t,n,i,r),Cu(t,n,e,o-1)):(Cu(t,n,e,o-1),Cu(t,n,i,r))}}function Pu(t,n,e){const r=t[n];t[n]=t[e],t[e]=r}function zu(t){return t[0]}function $u(t){return t[1]}const Du=1e-6;class Ru{constructor(){this._x0=this._y0=this._x1=this._y1=null,this._=""}moveTo(t,n){this._+=`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}`}closePath(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")}lineTo(t,n){this._+=`L${this._x1=+t},${this._y1=+n}`}arc(t,n,e){const r=(t=+t)+(e=+e),i=n=+n;if(e<0)throw new Error("negative radius");null===this._x1?this._+=`M${r},${i}`:(Math.abs(this._x1-r)>Du||Math.abs(this._y1-i)>Du)&&(this._+="L"+r+","+i),e&&(this._+=`A${e},${e},0,1,1,${t-e},${n}A${e},${e},0,1,1,${this._x1=r},${this._y1=i}`)}rect(t,n,e,r){this._+=`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}h${+e}v${+r}h${-e}Z`}value(){return this._||null}}class Fu{constructor(){this._=[]}moveTo(t,n){this._.push([t,n])}closePath(){this._.push(this._[0].slice())}lineTo(t,n){this._.push([t,n])}value(){return this._.length?this._:null}}class qu{constructor(t,[n,e,r,i]=[0,0,960,500]){if(!((r=+r)>=(n=+n)&&(i=+i)>=(e=+e)))throw new Error("invalid bounds");this.delaunay=t,this._circumcenters=new Float64Array(2*t.points.length),this.vectors=new Float64Array(2*t.points.length),this.xmax=r,this.xmin=n,this.ymax=i,this.ymin=e,this._init()}update(){return this.delaunay.update(),this._init(),this}_init(){const{delaunay:{points:t,hull:n,triangles:e},vectors:r}=this;let i,o;const a=this.circumcenters=this._circumcenters.subarray(0,e.length/3*2);for(let r,u,c=0,f=0,s=e.length;c1;)i-=2;for(let t=2;t0){if(n>=this.ymax)return null;(i=(this.ymax-n)/r)0){if(t>=this.xmax)return null;(i=(this.xmax-t)/e)this.xmax?2:0)|(nthis.ymax?8:0)}_simplify(t){if(t&&t.length>4){for(let n=0;n2&&function(t){const{triangles:n,coords:e}=t;for(let t=0;t1e-10)return!1}return!0}(t)){this.collinear=Int32Array.from({length:n.length/2},((t,n)=>n)).sort(((t,e)=>n[2*t]-n[2*e]||n[2*t+1]-n[2*e+1]));const t=this.collinear[0],e=this.collinear[this.collinear.length-1],r=[n[2*t],n[2*t+1],n[2*e],n[2*e+1]],i=1e-8*Math.hypot(r[3]-r[1],r[2]-r[0]);for(let t=0,e=n.length/2;t0&&(this.triangles=new Int32Array(3).fill(-1),this.halfedges=new Int32Array(3).fill(-1),this.triangles[0]=r[0],o[r[0]]=1,2===r.length&&(o[r[1]]=0,this.triangles[1]=r[1],this.triangles[2]=r[1]))}voronoi(t){return new qu(this,t)}*neighbors(t){const{inedges:n,hull:e,_hullIndex:r,halfedges:i,triangles:o,collinear:a}=this;if(a){const n=a.indexOf(t);return n>0&&(yield a[n-1]),void(n=0&&i!==e&&i!==r;)e=i;return i}_step(t,n,e){const{inedges:r,hull:i,_hullIndex:o,halfedges:a,triangles:u,points:c}=this;if(-1===r[t]||!c.length)return(t+1)%(c.length>>1);let f=t,s=Iu(n-c[2*t],2)+Iu(e-c[2*t+1],2);const l=r[t];let h=l;do{let r=u[h];const l=Iu(n-c[2*r],2)+Iu(e-c[2*r+1],2);if(l9999?"+"+Ku(n,6):Ku(n,4))+"-"+Ku(t.getUTCMonth()+1,2)+"-"+Ku(t.getUTCDate(),2)+(o?"T"+Ku(e,2)+":"+Ku(r,2)+":"+Ku(i,2)+"."+Ku(o,3)+"Z":i?"T"+Ku(e,2)+":"+Ku(r,2)+":"+Ku(i,2)+"Z":r||e?"T"+Ku(e,2)+":"+Ku(r,2)+"Z":"")}function Ju(t){var n=new RegExp('["'+t+"\n\r]"),e=t.charCodeAt(0);function r(t,n){var r,i=[],o=t.length,a=0,u=0,c=o<=0,f=!1;function s(){if(c)return Hu;if(f)return f=!1,ju;var n,r,i=a;if(t.charCodeAt(i)===Xu){for(;a++=o?c=!0:(r=t.charCodeAt(a++))===Gu?f=!0:r===Vu&&(f=!0,t.charCodeAt(a)===Gu&&++a),t.slice(i+1,n-1).replace(/""/g,'"')}for(;amc(n,e).then((n=>(new DOMParser).parseFromString(n,t)))}var Sc=Ac("application/xml"),Ec=Ac("text/html"),Nc=Ac("image/svg+xml");function kc(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,a,u,c,f,s,l,h,d=t._root,p={data:r},g=t._x0,y=t._y0,v=t._x1,_=t._y1;if(!d)return t._root=p,t;for(;d.length;)if((f=n>=(o=(g+v)/2))?g=o:v=o,(s=e>=(a=(y+_)/2))?y=a:_=a,i=d,!(d=d[l=s<<1|f]))return i[l]=p,t;if(u=+t._x.call(null,d.data),c=+t._y.call(null,d.data),n===u&&e===c)return p.next=d,i?i[l]=p:t._root=p,t;do{i=i?i[l]=new Array(4):t._root=new Array(4),(f=n>=(o=(g+v)/2))?g=o:v=o,(s=e>=(a=(y+_)/2))?y=a:_=a}while((l=s<<1|f)==(h=(c>=a)<<1|u>=o));return i[h]=d,i[l]=p,t}function Cc(t,n,e,r,i){this.node=t,this.x0=n,this.y0=e,this.x1=r,this.y1=i}function Pc(t){return t[0]}function zc(t){return t[1]}function $c(t,n,e){var r=new Dc(null==n?Pc:n,null==e?zc:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Dc(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function Rc(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}var Fc=$c.prototype=Dc.prototype;function qc(t){return function(){return t}}function Uc(t){return 1e-6*(t()-.5)}function Ic(t){return t.x+t.vx}function Oc(t){return t.y+t.vy}function Bc(t){return t.index}function Yc(t,n){var e=t.get(n);if(!e)throw new Error("node not found: "+n);return e}Fc.copy=function(){var t,n,e=new Dc(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return e;if(!r.length)return e._root=Rc(r),e;for(t=[{source:r,target:e._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(4)}):r.target[i]=Rc(n));return e},Fc.add=function(t){const n=+this._x.call(null,t),e=+this._y.call(null,t);return kc(this.cover(n,e),n,e,t)},Fc.addAll=function(t){var n,e,r,i,o=t.length,a=new Array(o),u=new Array(o),c=1/0,f=1/0,s=-1/0,l=-1/0;for(e=0;es&&(s=r),il&&(l=i));if(c>s||f>l)return this;for(this.cover(c,f).cover(s,l),e=0;et||t>=i||r>n||n>=o;)switch(u=(nh||(o=c.y0)>d||(a=c.x1)=v)<<1|t>=y)&&(c=p[p.length-1],p[p.length-1]=p[p.length-1-f],p[p.length-1-f]=c)}else{var _=t-+this._x.call(null,g.data),b=n-+this._y.call(null,g.data),m=_*_+b*b;if(m=(u=(p+y)/2))?p=u:y=u,(s=a>=(c=(g+v)/2))?g=c:v=c,n=d,!(d=d[l=s<<1|f]))return this;if(!d.length)break;(n[l+1&3]||n[l+2&3]||n[l+3&3])&&(e=n,h=l)}for(;d.data!==t;)if(r=d,!(d=d.next))return this;return(i=d.next)&&delete d.next,r?(i?r.next=i:delete r.next,this):n?(i?n[l]=i:delete n[l],(d=n[0]||n[1]||n[2]||n[3])&&d===(n[3]||n[2]||n[1]||n[0])&&!d.length&&(e?e[h]=d:this._root=d),this):(this._root=i,this)},Fc.removeAll=function(t){for(var n=0,e=t.length;n1?r[0]+r.slice(2):r,+t.slice(e+1)]}function Zc(t){return(t=Wc(Math.abs(t)))?t[1]:NaN}var Kc,Qc=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function Jc(t){if(!(n=Qc.exec(t)))throw new Error("invalid format: "+t);var n;return new tf({fill:n[1],align:n[2],sign:n[3],symbol:n[4],zero:n[5],width:n[6],comma:n[7],precision:n[8]&&n[8].slice(1),trim:n[9],type:n[10]})}function tf(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function nf(t,n){var e=Wc(t,n);if(!e)return t+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}Jc.prototype=tf.prototype,tf.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};var ef={"%":(t,n)=>(100*t).toFixed(n),b:t=>Math.round(t).toString(2),c:t=>t+"",d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:(t,n)=>t.toExponential(n),f:(t,n)=>t.toFixed(n),g:(t,n)=>t.toPrecision(n),o:t=>Math.round(t).toString(8),p:(t,n)=>nf(100*t,n),r:nf,s:function(t,n){var e=Wc(t,n);if(!e)return t+"";var r=e[0],i=e[1],o=i-(Kc=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,a=r.length;return o===a?r:o>a?r+new Array(o-a+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+Wc(t,Math.max(0,n+o-1))[0]},X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function rf(t){return t}var of,af=Array.prototype.map,uf=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function cf(t){var n,e,r=void 0===t.grouping||void 0===t.thousands?rf:(n=af.call(t.grouping,Number),e=t.thousands+"",function(t,r){for(var i=t.length,o=[],a=0,u=n[0],c=0;i>0&&u>0&&(c+u+1>r&&(u=Math.max(1,r-c)),o.push(t.substring(i-=u,i+u)),!((c+=u+1)>r));)u=n[a=(a+1)%n.length];return o.reverse().join(e)}),i=void 0===t.currency?"":t.currency[0]+"",o=void 0===t.currency?"":t.currency[1]+"",a=void 0===t.decimal?".":t.decimal+"",u=void 0===t.numerals?rf:function(t){return function(n){return n.replace(/[0-9]/g,(function(n){return t[+n]}))}}(af.call(t.numerals,String)),c=void 0===t.percent?"%":t.percent+"",f=void 0===t.minus?"−":t.minus+"",s=void 0===t.nan?"NaN":t.nan+"";function l(t){var n=(t=Jc(t)).fill,e=t.align,l=t.sign,h=t.symbol,d=t.zero,p=t.width,g=t.comma,y=t.precision,v=t.trim,_=t.type;"n"===_?(g=!0,_="g"):ef[_]||(void 0===y&&(y=12),v=!0,_="g"),(d||"0"===n&&"="===e)&&(d=!0,n="0",e="=");var b="$"===h?i:"#"===h&&/[boxX]/.test(_)?"0"+_.toLowerCase():"",m="$"===h?o:/[%p]/.test(_)?c:"",x=ef[_],w=/[defgprs%]/.test(_);function M(t){var i,o,c,h=b,M=m;if("c"===_)M=x(t)+M,t="";else{var T=(t=+t)<0||1/t<0;if(t=isNaN(t)?s:x(Math.abs(t),y),v&&(t=function(t){t:for(var n,e=t.length,r=1,i=-1;r0&&(i=0)}return i>0?t.slice(0,i)+t.slice(n+1):t}(t)),T&&0==+t&&"+"!==l&&(T=!1),h=(T?"("===l?l:f:"-"===l||"("===l?"":l)+h,M=("s"===_?uf[8+Kc/3]:"")+M+(T&&"("===l?")":""),w)for(i=-1,o=t.length;++i(c=t.charCodeAt(i))||c>57){M=(46===c?a+t.slice(i+1):t.slice(i))+M,t=t.slice(0,i);break}}g&&!d&&(t=r(t,1/0));var A=h.length+t.length+M.length,S=A>1)+h+t+M+S.slice(A);break;default:t=S+h+t+M}return u(t)}return y=void 0===y?6:/[gprs]/.test(_)?Math.max(1,Math.min(21,y)):Math.max(0,Math.min(20,y)),M.toString=function(){return t+""},M}return{format:l,formatPrefix:function(t,n){var e=l(((t=Jc(t)).type="f",t)),r=3*Math.max(-8,Math.min(8,Math.floor(Zc(n)/3))),i=Math.pow(10,-r),o=uf[8+r/3];return function(t){return e(i*t)+o}}}}function ff(n){return of=cf(n),t.format=of.format,t.formatPrefix=of.formatPrefix,of}function sf(t){return Math.max(0,-Zc(Math.abs(t)))}function lf(t,n){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(Zc(n)/3)))-Zc(Math.abs(t)))}function hf(t,n){return t=Math.abs(t),n=Math.abs(n)-t,Math.max(0,Zc(n)-Zc(t))+1}t.format=void 0,t.formatPrefix=void 0,ff({thousands:",",grouping:[3],currency:["$",""]});var df=1e-6,pf=1e-12,gf=Math.PI,yf=gf/2,vf=gf/4,_f=2*gf,bf=180/gf,mf=gf/180,xf=Math.abs,wf=Math.atan,Mf=Math.atan2,Tf=Math.cos,Af=Math.ceil,Sf=Math.exp,Ef=Math.hypot,Nf=Math.log,kf=Math.pow,Cf=Math.sin,Pf=Math.sign||function(t){return t>0?1:t<0?-1:0},zf=Math.sqrt,$f=Math.tan;function Df(t){return t>1?0:t<-1?gf:Math.acos(t)}function Rf(t){return t>1?yf:t<-1?-yf:Math.asin(t)}function Ff(t){return(t=Cf(t/2))*t}function qf(){}function Uf(t,n){t&&Of.hasOwnProperty(t.type)&&Of[t.type](t,n)}var If={Feature:function(t,n){Uf(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r=0?1:-1,i=r*e,o=Tf(n=(n*=mf)/2+vf),a=Cf(n),u=Vf*a,c=Gf*o+u*Tf(i),f=u*r*Cf(i);as.add(Mf(f,c)),Xf=t,Gf=o,Vf=a}function ds(t){return[Mf(t[1],t[0]),Rf(t[2])]}function ps(t){var n=t[0],e=t[1],r=Tf(e);return[r*Tf(n),r*Cf(n),Cf(e)]}function gs(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function ys(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function vs(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function _s(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function bs(t){var n=zf(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}var ms,xs,ws,Ms,Ts,As,Ss,Es,Ns,ks,Cs,Ps,zs,$s,Ds,Rs,Fs={point:qs,lineStart:Is,lineEnd:Os,polygonStart:function(){Fs.point=Bs,Fs.lineStart=Ys,Fs.lineEnd=Ls,rs=new T,cs.polygonStart()},polygonEnd:function(){cs.polygonEnd(),Fs.point=qs,Fs.lineStart=Is,Fs.lineEnd=Os,as<0?(Wf=-(Kf=180),Zf=-(Qf=90)):rs>df?Qf=90:rs<-df&&(Zf=-90),os[0]=Wf,os[1]=Kf},sphere:function(){Wf=-(Kf=180),Zf=-(Qf=90)}};function qs(t,n){is.push(os=[Wf=t,Kf=t]),nQf&&(Qf=n)}function Us(t,n){var e=ps([t*mf,n*mf]);if(es){var r=ys(es,e),i=ys([r[1],-r[0],0],r);bs(i),i=ds(i);var o,a=t-Jf,u=a>0?1:-1,c=i[0]*bf*u,f=xf(a)>180;f^(u*JfQf&&(Qf=o):f^(u*Jf<(c=(c+360)%360-180)&&cQf&&(Qf=n)),f?tjs(Wf,Kf)&&(Kf=t):js(t,Kf)>js(Wf,Kf)&&(Wf=t):Kf>=Wf?(tKf&&(Kf=t)):t>Jf?js(Wf,t)>js(Wf,Kf)&&(Kf=t):js(t,Kf)>js(Wf,Kf)&&(Wf=t)}else is.push(os=[Wf=t,Kf=t]);nQf&&(Qf=n),es=e,Jf=t}function Is(){Fs.point=Us}function Os(){os[0]=Wf,os[1]=Kf,Fs.point=qs,es=null}function Bs(t,n){if(es){var e=t-Jf;rs.add(xf(e)>180?e+(e>0?360:-360):e)}else ts=t,ns=n;cs.point(t,n),Us(t,n)}function Ys(){cs.lineStart()}function Ls(){Bs(ts,ns),cs.lineEnd(),xf(rs)>df&&(Wf=-(Kf=180)),os[0]=Wf,os[1]=Kf,es=null}function js(t,n){return(n-=t)<0?n+360:n}function Hs(t,n){return t[0]-n[0]}function Xs(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:ngf&&(t-=Math.round(t/_f)*_f),[t,n]}function ul(t,n,e){return(t%=_f)?n||e?ol(fl(t),sl(n,e)):fl(t):n||e?sl(n,e):al}function cl(t){return function(n,e){return xf(n+=t)>gf&&(n-=Math.round(n/_f)*_f),[n,e]}}function fl(t){var n=cl(t);return n.invert=cl(-t),n}function sl(t,n){var e=Tf(t),r=Cf(t),i=Tf(n),o=Cf(n);function a(t,n){var a=Tf(n),u=Tf(t)*a,c=Cf(t)*a,f=Cf(n),s=f*e+u*r;return[Mf(c*i-s*o,u*e-f*r),Rf(s*i+c*o)]}return a.invert=function(t,n){var a=Tf(n),u=Tf(t)*a,c=Cf(t)*a,f=Cf(n),s=f*i-c*o;return[Mf(c*i+f*o,u*e+s*r),Rf(s*e-u*r)]},a}function ll(t){function n(n){return(n=t(n[0]*mf,n[1]*mf))[0]*=bf,n[1]*=bf,n}return t=ul(t[0]*mf,t[1]*mf,t.length>2?t[2]*mf:0),n.invert=function(n){return(n=t.invert(n[0]*mf,n[1]*mf))[0]*=bf,n[1]*=bf,n},n}function hl(t,n,e,r,i,o){if(e){var a=Tf(n),u=Cf(n),c=r*e;null==i?(i=n+r*_f,o=n-c/2):(i=dl(a,i),o=dl(a,o),(r>0?io)&&(i+=r*_f));for(var f,s=i;r>0?s>o:s1&&n.push(n.pop().concat(n.shift()))},result:function(){var e=n;return n=[],t=null,e}}}function gl(t,n){return xf(t[0]-n[0])=0;--o)i.point((s=f[o])[0],s[1]);else r(h.x,h.p.x,-1,i);h=h.p}f=(h=h.o).z,d=!d}while(!h.v);i.lineEnd()}}}function _l(t){if(n=t.length){for(var n,e,r=0,i=t[0];++r=0?1:-1,E=S*A,N=E>gf,k=y*w;if(c.add(Mf(k*S*Cf(E),v*M+k*Tf(E))),a+=N?A+S*_f:A,N^p>=e^m>=e){var C=ys(ps(d),ps(b));bs(C);var P=ys(o,C);bs(P);var z=(N^A>=0?-1:1)*Rf(P[2]);(r>z||r===z&&(C[0]||C[1]))&&(u+=N^A>=0?1:-1)}}return(a<-df||a0){for(l||(i.polygonStart(),l=!0),i.lineStart(),t=0;t1&&2&c&&h.push(h.pop().concat(h.shift())),a.push(h.filter(wl))}return h}}function wl(t){return t.length>1}function Ml(t,n){return((t=t.x)[0]<0?t[1]-yf-df:yf-t[1])-((n=n.x)[0]<0?n[1]-yf-df:yf-n[1])}al.invert=al;var Tl=xl((function(){return!0}),(function(t){var n,e=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lineStart(),n=1},point:function(o,a){var u=o>0?gf:-gf,c=xf(o-e);xf(c-gf)0?yf:-yf),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(u,r),t.point(o,r),n=0):i!==u&&c>=gf&&(xf(e-i)df?wf((Cf(n)*(o=Tf(r))*Cf(e)-Cf(r)*(i=Tf(n))*Cf(t))/(i*o*a)):(n+r)/2}(e,r,o,a),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(u,r),n=0),t.point(e=o,r=a),i=u},lineEnd:function(){t.lineEnd(),e=r=NaN},clean:function(){return 2-n}}}),(function(t,n,e,r){var i;if(null==t)i=e*yf,r.point(-gf,i),r.point(0,i),r.point(gf,i),r.point(gf,0),r.point(gf,-i),r.point(0,-i),r.point(-gf,-i),r.point(-gf,0),r.point(-gf,i);else if(xf(t[0]-n[0])>df){var o=t[0]0,i=xf(n)>df;function o(t,e){return Tf(t)*Tf(e)>n}function a(t,e,r){var i=[1,0,0],o=ys(ps(t),ps(e)),a=gs(o,o),u=o[0],c=a-u*u;if(!c)return!r&&t;var f=n*a/c,s=-n*u/c,l=ys(i,o),h=_s(i,f);vs(h,_s(o,s));var d=l,p=gs(h,d),g=gs(d,d),y=p*p-g*(gs(h,h)-1);if(!(y<0)){var v=zf(y),_=_s(d,(-p-v)/g);if(vs(_,h),_=ds(_),!r)return _;var b,m=t[0],x=e[0],w=t[1],M=e[1];x0^_[1]<(xf(_[0]-m)gf^(m<=_[0]&&_[0]<=x)){var S=_s(d,(-p+v)/g);return vs(S,h),[_,ds(S)]}}}function u(n,e){var i=r?t:gf-t,o=0;return n<-i?o|=1:n>i&&(o|=2),e<-i?o|=4:e>i&&(o|=8),o}return xl(o,(function(t){var n,e,c,f,s;return{lineStart:function(){f=c=!1,s=1},point:function(l,h){var d,p=[l,h],g=o(l,h),y=r?g?0:u(l,h):g?u(l+(l<0?gf:-gf),h):0;if(!n&&(f=c=g)&&t.lineStart(),g!==c&&(!(d=a(n,p))||gl(n,d)||gl(p,d))&&(p[2]=1),g!==c)s=0,g?(t.lineStart(),d=a(p,n),t.point(d[0],d[1])):(d=a(n,p),t.point(d[0],d[1],2),t.lineEnd()),n=d;else if(i&&n&&r^g){var v;y&e||!(v=a(p,n,!0))||(s=0,r?(t.lineStart(),t.point(v[0][0],v[0][1]),t.point(v[1][0],v[1][1]),t.lineEnd()):(t.point(v[1][0],v[1][1]),t.lineEnd(),t.lineStart(),t.point(v[0][0],v[0][1],3)))}!g||n&&gl(n,p)||t.point(p[0],p[1]),n=p,c=g,e=y},lineEnd:function(){c&&t.lineEnd(),n=null},clean:function(){return s|(f&&c)<<1}}}),(function(n,r,i,o){hl(o,t,e,i,n,r)}),r?[0,-t]:[-gf,t-gf])}var Sl,El,Nl,kl,Cl=1e9,Pl=-Cl;function zl(t,n,e,r){function i(i,o){return t<=i&&i<=e&&n<=o&&o<=r}function o(i,o,u,f){var s=0,l=0;if(null==i||(s=a(i,u))!==(l=a(o,u))||c(i,o)<0^u>0)do{f.point(0===s||3===s?t:e,s>1?r:n)}while((s=(s+u+4)%4)!==l);else f.point(o[0],o[1])}function a(r,i){return xf(r[0]-t)0?0:3:xf(r[0]-e)0?2:1:xf(r[1]-n)0?1:0:i>0?3:2}function u(t,n){return c(t.x,n.x)}function c(t,n){var e=a(t,1),r=a(n,1);return e!==r?e-r:0===e?n[1]-t[1]:1===e?t[0]-n[0]:2===e?t[1]-n[1]:n[0]-t[0]}return function(a){var c,f,s,l,h,d,p,g,y,v,_,b=a,m=pl(),x={point:w,lineStart:function(){x.point=M,f&&f.push(s=[]);v=!0,y=!1,p=g=NaN},lineEnd:function(){c&&(M(l,h),d&&y&&m.rejoin(),c.push(m.result()));x.point=w,y&&b.lineEnd()},polygonStart:function(){b=m,c=[],f=[],_=!0},polygonEnd:function(){var n=function(){for(var n=0,e=0,i=f.length;er&&(h-o)*(r-a)>(d-a)*(t-o)&&++n:d<=r&&(h-o)*(r-a)<(d-a)*(t-o)&&--n;return n}(),e=_&&n,i=(c=ft(c)).length;(e||i)&&(a.polygonStart(),e&&(a.lineStart(),o(null,null,1,a),a.lineEnd()),i&&vl(c,u,n,o,a),a.polygonEnd());b=a,c=f=s=null}};function w(t,n){i(t,n)&&b.point(t,n)}function M(o,a){var u=i(o,a);if(f&&s.push([o,a]),v)l=o,h=a,d=u,v=!1,u&&(b.lineStart(),b.point(o,a));else if(u&&y)b.point(o,a);else{var c=[p=Math.max(Pl,Math.min(Cl,p)),g=Math.max(Pl,Math.min(Cl,g))],m=[o=Math.max(Pl,Math.min(Cl,o)),a=Math.max(Pl,Math.min(Cl,a))];!function(t,n,e,r,i,o){var a,u=t[0],c=t[1],f=0,s=1,l=n[0]-u,h=n[1]-c;if(a=e-u,l||!(a>0)){if(a/=l,l<0){if(a0){if(a>s)return;a>f&&(f=a)}if(a=i-u,l||!(a<0)){if(a/=l,l<0){if(a>s)return;a>f&&(f=a)}else if(l>0){if(a0)){if(a/=h,h<0){if(a0){if(a>s)return;a>f&&(f=a)}if(a=o-c,h||!(a<0)){if(a/=h,h<0){if(a>s)return;a>f&&(f=a)}else if(h>0){if(a0&&(t[0]=u+f*l,t[1]=c+f*h),s<1&&(n[0]=u+s*l,n[1]=c+s*h),!0}}}}}(c,m,t,n,e,r)?u&&(b.lineStart(),b.point(o,a),_=!1):(y||(b.lineStart(),b.point(c[0],c[1])),b.point(m[0],m[1]),u||b.lineEnd(),_=!1)}p=o,g=a,y=u}return x}}var $l={sphere:qf,point:qf,lineStart:function(){$l.point=Rl,$l.lineEnd=Dl},lineEnd:qf,polygonStart:qf,polygonEnd:qf};function Dl(){$l.point=$l.lineEnd=qf}function Rl(t,n){El=t*=mf,Nl=Cf(n*=mf),kl=Tf(n),$l.point=Fl}function Fl(t,n){t*=mf;var e=Cf(n*=mf),r=Tf(n),i=xf(t-El),o=Tf(i),a=r*Cf(i),u=kl*e-Nl*r*o,c=Nl*e+kl*r*o;Sl.add(Mf(zf(a*a+u*u),c)),El=t,Nl=e,kl=r}function ql(t){return Sl=new T,Lf(t,$l),+Sl}var Ul=[null,null],Il={type:"LineString",coordinates:Ul};function Ol(t,n){return Ul[0]=t,Ul[1]=n,ql(Il)}var Bl={Feature:function(t,n){return Ll(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r0&&(i=Ol(t[o],t[o-1]))>0&&e<=i&&r<=i&&(e+r-i)*(1-Math.pow((e-r)/i,2))df})).map(c)).concat(lt(Af(o/d)*d,i,d).filter((function(t){return xf(t%g)>df})).map(f))}return v.lines=function(){return _().map((function(t){return{type:"LineString",coordinates:t}}))},v.outline=function(){return{type:"Polygon",coordinates:[s(r).concat(l(a).slice(1),s(e).reverse().slice(1),l(u).reverse().slice(1))]}},v.extent=function(t){return arguments.length?v.extentMajor(t).extentMinor(t):v.extentMinor()},v.extentMajor=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],u=+t[0][1],a=+t[1][1],r>e&&(t=r,r=e,e=t),u>a&&(t=u,u=a,a=t),v.precision(y)):[[r,u],[e,a]]},v.extentMinor=function(e){return arguments.length?(n=+e[0][0],t=+e[1][0],o=+e[0][1],i=+e[1][1],n>t&&(e=n,n=t,t=e),o>i&&(e=o,o=i,i=e),v.precision(y)):[[n,o],[t,i]]},v.step=function(t){return arguments.length?v.stepMajor(t).stepMinor(t):v.stepMinor()},v.stepMajor=function(t){return arguments.length?(p=+t[0],g=+t[1],v):[p,g]},v.stepMinor=function(t){return arguments.length?(h=+t[0],d=+t[1],v):[h,d]},v.precision=function(h){return arguments.length?(y=+h,c=Wl(o,i,90),f=Zl(n,t,y),s=Wl(u,a,90),l=Zl(r,e,y),v):y},v.extentMajor([[-180,-90+df],[180,90-df]]).extentMinor([[-180,-80-df],[180,80+df]])}var Ql,Jl,th,nh,eh=t=>t,rh=new T,ih=new T,oh={point:qf,lineStart:qf,lineEnd:qf,polygonStart:function(){oh.lineStart=ah,oh.lineEnd=fh},polygonEnd:function(){oh.lineStart=oh.lineEnd=oh.point=qf,rh.add(xf(ih)),ih=new T},result:function(){var t=rh/2;return rh=new T,t}};function ah(){oh.point=uh}function uh(t,n){oh.point=ch,Ql=th=t,Jl=nh=n}function ch(t,n){ih.add(nh*t-th*n),th=t,nh=n}function fh(){ch(Ql,Jl)}var sh=oh,lh=1/0,hh=lh,dh=-lh,ph=dh,gh={point:function(t,n){tdh&&(dh=t);nph&&(ph=n)},lineStart:qf,lineEnd:qf,polygonStart:qf,polygonEnd:qf,result:function(){var t=[[lh,hh],[dh,ph]];return dh=ph=-(hh=lh=1/0),t}};var yh,vh,_h,bh,mh=gh,xh=0,wh=0,Mh=0,Th=0,Ah=0,Sh=0,Eh=0,Nh=0,kh=0,Ch={point:Ph,lineStart:zh,lineEnd:Rh,polygonStart:function(){Ch.lineStart=Fh,Ch.lineEnd=qh},polygonEnd:function(){Ch.point=Ph,Ch.lineStart=zh,Ch.lineEnd=Rh},result:function(){var t=kh?[Eh/kh,Nh/kh]:Sh?[Th/Sh,Ah/Sh]:Mh?[xh/Mh,wh/Mh]:[NaN,NaN];return xh=wh=Mh=Th=Ah=Sh=Eh=Nh=kh=0,t}};function Ph(t,n){xh+=t,wh+=n,++Mh}function zh(){Ch.point=$h}function $h(t,n){Ch.point=Dh,Ph(_h=t,bh=n)}function Dh(t,n){var e=t-_h,r=n-bh,i=zf(e*e+r*r);Th+=i*(_h+t)/2,Ah+=i*(bh+n)/2,Sh+=i,Ph(_h=t,bh=n)}function Rh(){Ch.point=Ph}function Fh(){Ch.point=Uh}function qh(){Ih(yh,vh)}function Uh(t,n){Ch.point=Ih,Ph(yh=_h=t,vh=bh=n)}function Ih(t,n){var e=t-_h,r=n-bh,i=zf(e*e+r*r);Th+=i*(_h+t)/2,Ah+=i*(bh+n)/2,Sh+=i,Eh+=(i=bh*t-_h*n)*(_h+t),Nh+=i*(bh+n),kh+=3*i,Ph(_h=t,bh=n)}var Oh=Ch;function Bh(t){this._context=t}Bh.prototype={_radius:4.5,pointRadius:function(t){return this._radius=t,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._context.closePath(),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._context.moveTo(t,n),this._point=1;break;case 1:this._context.lineTo(t,n);break;default:this._context.moveTo(t+this._radius,n),this._context.arc(t,n,this._radius,0,_f)}},result:qf};var Yh,Lh,jh,Hh,Xh,Gh=new T,Vh={point:qf,lineStart:function(){Vh.point=Wh},lineEnd:function(){Yh&&Zh(Lh,jh),Vh.point=qf},polygonStart:function(){Yh=!0},polygonEnd:function(){Yh=null},result:function(){var t=+Gh;return Gh=new T,t}};function Wh(t,n){Vh.point=Zh,Lh=Hh=t,jh=Xh=n}function Zh(t,n){Hh-=t,Xh-=n,Gh.add(zf(Hh*Hh+Xh*Xh)),Hh=t,Xh=n}var Kh=Vh;let Qh,Jh,td,nd;class ed{constructor(t){this._append=null==t?rd:function(t){const n=Math.floor(t);if(!(n>=0))throw new RangeError(`invalid digits: ${t}`);if(n>15)return rd;if(n!==Qh){const t=10**n;Qh=n,Jh=function(n){let e=1;this._+=n[0];for(const r=n.length;e4*n&&g--){var m=a+h,x=u+d,w=c+p,M=zf(m*m+x*x+w*w),T=Rf(w/=M),A=xf(xf(w)-1)n||xf((v*k+_*C)/b-.5)>.3||a*h+u*d+c*p2?t[2]%360*mf:0,k()):[y*bf,v*bf,_*bf]},E.angle=function(t){return arguments.length?(b=t%360*mf,k()):b*bf},E.reflectX=function(t){return arguments.length?(m=t?-1:1,k()):m<0},E.reflectY=function(t){return arguments.length?(x=t?-1:1,k()):x<0},E.precision=function(t){return arguments.length?(a=dd(u,S=t*t),C()):zf(S)},E.fitExtent=function(t,n){return ud(E,t,n)},E.fitSize=function(t,n){return cd(E,t,n)},E.fitWidth=function(t,n){return fd(E,t,n)},E.fitHeight=function(t,n){return sd(E,t,n)},function(){return n=t.apply(this,arguments),E.invert=n.invert&&N,k()}}function _d(t){var n=0,e=gf/3,r=vd(t),i=r(n,e);return i.parallels=function(t){return arguments.length?r(n=t[0]*mf,e=t[1]*mf):[n*bf,e*bf]},i}function bd(t,n){var e=Cf(t),r=(e+Cf(n))/2;if(xf(r)0?n<-yf+df&&(n=-yf+df):n>yf-df&&(n=yf-df);var e=i/kf(Nd(n),r);return[e*Cf(r*t),i-e*Tf(r*t)]}return o.invert=function(t,n){var e=i-n,o=Pf(r)*zf(t*t+e*e),a=Mf(t,xf(e))*Pf(e);return e*r<0&&(a-=gf*Pf(t)*Pf(e)),[a/r,2*wf(kf(i/o,1/r))-yf]},o}function Cd(t,n){return[t,n]}function Pd(t,n){var e=Tf(t),r=t===n?Cf(t):(e-Tf(n))/(n-t),i=e/r+t;if(xf(r)=0;)n+=e[r].value;else n=1;t.value=n}function Gd(t,n){t instanceof Map?(t=[void 0,t],void 0===n&&(n=Wd)):void 0===n&&(n=Vd);for(var e,r,i,o,a,u=new Qd(t),c=[u];e=c.pop();)if((i=n(e.data))&&(a=(i=Array.from(i)).length))for(e.children=i,o=a-1;o>=0;--o)c.push(r=i[o]=new Qd(i[o])),r.parent=e,r.depth=e.depth+1;return u.eachBefore(Kd)}function Vd(t){return t.children}function Wd(t){return Array.isArray(t)?t[1]:null}function Zd(t){void 0!==t.data.value&&(t.value=t.data.value),t.data=t.data.data}function Kd(t){var n=0;do{t.height=n}while((t=t.parent)&&t.height<++n)}function Qd(t){this.data=t,this.depth=this.height=0,this.parent=null}function Jd(t){return null==t?null:tp(t)}function tp(t){if("function"!=typeof t)throw new Error;return t}function np(){return 0}function ep(t){return function(){return t}}qd.invert=function(t,n){for(var e,r=n,i=r*r,o=i*i*i,a=0;a<12&&(o=(i=(r-=e=(r*(zd+$d*i+o*(Dd+Rd*i))-n)/(zd+3*$d*i+o*(7*Dd+9*Rd*i)))*r)*i*i,!(xf(e)df&&--i>0);return[t/(.8707+(o=r*r)*(o*(o*o*o*(.003971-.001529*o)-.013791)-.131979)),r]},Od.invert=Md(Rf),Bd.invert=Md((function(t){return 2*wf(t)})),Yd.invert=function(t,n){return[-n,2*wf(Sf(t))-yf]},Qd.prototype=Gd.prototype={constructor:Qd,count:function(){return this.eachAfter(Xd)},each:function(t,n){let e=-1;for(const r of this)t.call(n,r,++e,this);return this},eachAfter:function(t,n){for(var e,r,i,o=this,a=[o],u=[],c=-1;o=a.pop();)if(u.push(o),e=o.children)for(r=0,i=e.length;r=0;--r)o.push(e[r]);return this},find:function(t,n){let e=-1;for(const r of this)if(t.call(n,r,++e,this))return r},sum:function(t){return this.eachAfter((function(n){for(var e=+t(n.data)||0,r=n.children,i=r&&r.length;--i>=0;)e+=r[i].value;n.value=e}))},sort:function(t){return this.eachBefore((function(n){n.children&&n.children.sort(t)}))},path:function(t){for(var n=this,e=function(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i=null;t=e.pop(),n=r.pop();for(;t===n;)i=t,t=e.pop(),n=r.pop();return i}(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n},descendants:function(){return Array.from(this)},leaves:function(){var t=[];return this.eachBefore((function(n){n.children||t.push(n)})),t},links:function(){var t=this,n=[];return t.each((function(e){e!==t&&n.push({source:e.parent,target:e})})),n},copy:function(){return Gd(this).eachBefore(Zd)},[Symbol.iterator]:function*(){var t,n,e,r,i=this,o=[i];do{for(t=o.reverse(),o=[];i=t.pop();)if(yield i,n=i.children)for(e=0,r=n.length;e(t=(rp*t+ip)%op)/op}function up(t,n){for(var e,r,i=0,o=(t=function(t,n){let e,r,i=t.length;for(;i;)r=n()*i--|0,e=t[i],t[i]=t[r],t[r]=e;return t}(Array.from(t),n)).length,a=[];i0&&e*e>r*r+i*i}function lp(t,n){for(var e=0;e1e-6?(E+Math.sqrt(E*E-4*S*N))/(2*S):N/E);return{x:r+w+M*k,y:i+T+A*k,r:k}}function gp(t,n,e){var r,i,o,a,u=t.x-n.x,c=t.y-n.y,f=u*u+c*c;f?(i=n.r+e.r,i*=i,a=t.r+e.r,i>(a*=a)?(r=(f+a-i)/(2*f),o=Math.sqrt(Math.max(0,a/f-r*r)),e.x=t.x-r*u-o*c,e.y=t.y-r*c+o*u):(r=(f+i-a)/(2*f),o=Math.sqrt(Math.max(0,i/f-r*r)),e.x=n.x+r*u-o*c,e.y=n.y+r*c+o*u)):(e.x=n.x+e.r,e.y=n.y)}function yp(t,n){var e=t.r+n.r-1e-6,r=n.x-t.x,i=n.y-t.y;return e>0&&e*e>r*r+i*i}function vp(t){var n=t._,e=t.next._,r=n.r+e.r,i=(n.x*e.r+e.x*n.r)/r,o=(n.y*e.r+e.y*n.r)/r;return i*i+o*o}function _p(t){this._=t,this.next=null,this.previous=null}function bp(t,n){if(!(o=(t=function(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}(t)).length))return 0;var e,r,i,o,a,u,c,f,s,l,h;if((e=t[0]).x=0,e.y=0,!(o>1))return e.r;if(r=t[1],e.x=-r.r,r.x=e.r,r.y=0,!(o>2))return e.r+r.r;gp(r,e,i=t[2]),e=new _p(e),r=new _p(r),i=new _p(i),e.next=i.previous=r,r.next=e.previous=i,i.next=r.previous=e;t:for(c=3;c1&&!zp(t,n););return t.slice(0,n)}function zp(t,n){if("/"===t[n]){let e=0;for(;n>0&&"\\"===t[--n];)++e;if(0==(1&e))return!0}return!1}function $p(t,n){return t.parent===n.parent?1:2}function Dp(t){var n=t.children;return n?n[0]:t.t}function Rp(t){var n=t.children;return n?n[n.length-1]:t.t}function Fp(t,n,e){var r=e/(n.i-t.i);n.c-=r,n.s+=e,t.c+=r,n.z+=e,n.m+=e}function qp(t,n,e){return t.a.parent===n.parent?t.a:e}function Up(t,n){this._=t,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=n}function Ip(t,n,e,r,i){for(var o,a=t.children,u=-1,c=a.length,f=t.value&&(i-e)/t.value;++uh&&(h=u),y=s*s*g,(d=Math.max(h/y,y/l))>p){s-=u;break}p=d}v.push(a={value:s,dice:c1?n:1)},e}(Op);var Lp=function t(n){function e(t,e,r,i,o){if((a=t._squarify)&&a.ratio===n)for(var a,u,c,f,s,l=-1,h=a.length,d=t.value;++l1?n:1)},e}(Op);function jp(t,n,e){return(n[0]-t[0])*(e[1]-t[1])-(n[1]-t[1])*(e[0]-t[0])}function Hp(t,n){return t[0]-n[0]||t[1]-n[1]}function Xp(t){const n=t.length,e=[0,1];let r,i=2;for(r=2;r1&&jp(t[e[i-2]],t[e[i-1]],t[r])<=0;)--i;e[i++]=r}return e.slice(0,i)}var Gp=Math.random,Vp=function t(n){function e(t,e){return t=null==t?0:+t,e=null==e?1:+e,1===arguments.length?(e=t,t=0):e-=t,function(){return n()*e+t}}return e.source=t,e}(Gp),Wp=function t(n){function e(t,e){return arguments.length<2&&(e=t,t=0),t=Math.floor(t),e=Math.floor(e)-t,function(){return Math.floor(n()*e+t)}}return e.source=t,e}(Gp),Zp=function t(n){function e(t,e){var r,i;return t=null==t?0:+t,e=null==e?1:+e,function(){var o;if(null!=r)o=r,r=null;else do{r=2*n()-1,o=2*n()-1,i=r*r+o*o}while(!i||i>1);return t+e*o*Math.sqrt(-2*Math.log(i)/i)}}return e.source=t,e}(Gp),Kp=function t(n){var e=Zp.source(n);function r(){var t=e.apply(this,arguments);return function(){return Math.exp(t())}}return r.source=t,r}(Gp),Qp=function t(n){function e(t){return(t=+t)<=0?()=>0:function(){for(var e=0,r=t;r>1;--r)e+=n();return e+r*n()}}return e.source=t,e}(Gp),Jp=function t(n){var e=Qp.source(n);function r(t){if(0==(t=+t))return n;var r=e(t);return function(){return r()/t}}return r.source=t,r}(Gp),tg=function t(n){function e(t){return function(){return-Math.log1p(-n())/t}}return e.source=t,e}(Gp),ng=function t(n){function e(t){if((t=+t)<0)throw new RangeError("invalid alpha");return t=1/-t,function(){return Math.pow(1-n(),t)}}return e.source=t,e}(Gp),eg=function t(n){function e(t){if((t=+t)<0||t>1)throw new RangeError("invalid p");return function(){return Math.floor(n()+t)}}return e.source=t,e}(Gp),rg=function t(n){function e(t){if((t=+t)<0||t>1)throw new RangeError("invalid p");return 0===t?()=>1/0:1===t?()=>1:(t=Math.log1p(-t),function(){return 1+Math.floor(Math.log1p(-n())/t)})}return e.source=t,e}(Gp),ig=function t(n){var e=Zp.source(n)();function r(t,r){if((t=+t)<0)throw new RangeError("invalid k");if(0===t)return()=>0;if(r=null==r?1:+r,1===t)return()=>-Math.log1p(-n())*r;var i=(t<1?t+1:t)-1/3,o=1/(3*Math.sqrt(i)),a=t<1?()=>Math.pow(n(),1/t):()=>1;return function(){do{do{var t=e(),u=1+o*t}while(u<=0);u*=u*u;var c=1-n()}while(c>=1-.0331*t*t*t*t&&Math.log(c)>=.5*t*t+i*(1-u+Math.log(u)));return i*u*a()*r}}return r.source=t,r}(Gp),og=function t(n){var e=ig.source(n);function r(t,n){var r=e(t),i=e(n);return function(){var t=r();return 0===t?0:t/(t+i())}}return r.source=t,r}(Gp),ag=function t(n){var e=rg.source(n),r=og.source(n);function i(t,n){return t=+t,(n=+n)>=1?()=>t:n<=0?()=>0:function(){for(var i=0,o=t,a=n;o*a>16&&o*(1-a)>16;){var u=Math.floor((o+1)*a),c=r(u,o-u+1)();c<=a?(i+=u,o-=u,a=(a-c)/(1-c)):(o=u-1,a/=c)}for(var f=a<.5,s=e(f?a:1-a),l=s(),h=0;l<=o;++h)l+=s();return i+(f?h:o-h)}}return i.source=t,i}(Gp),ug=function t(n){function e(t,e,r){var i;return 0==(t=+t)?i=t=>-Math.log(t):(t=1/t,i=n=>Math.pow(n,t)),e=null==e?0:+e,r=null==r?1:+r,function(){return e+r*i(-Math.log1p(-n()))}}return e.source=t,e}(Gp),cg=function t(n){function e(t,e){return t=null==t?0:+t,e=null==e?1:+e,function(){return t+e*Math.tan(Math.PI*n())}}return e.source=t,e}(Gp),fg=function t(n){function e(t,e){return t=null==t?0:+t,e=null==e?1:+e,function(){var r=n();return t+e*Math.log(r/(1-r))}}return e.source=t,e}(Gp),sg=function t(n){var e=ig.source(n),r=ag.source(n);function i(t){return function(){for(var i=0,o=t;o>16;){var a=Math.floor(.875*o),u=e(a)();if(u>o)return i+r(a-1,o/u)();i+=a,o-=u}for(var c=-Math.log1p(-n()),f=0;c<=o;++f)c-=Math.log1p(-n());return i+f}}return i.source=t,i}(Gp);const lg=1/4294967296;function hg(t,n){switch(arguments.length){case 0:break;case 1:this.range(t);break;default:this.range(n).domain(t)}return this}function dg(t,n){switch(arguments.length){case 0:break;case 1:"function"==typeof t?this.interpolator(t):this.range(t);break;default:this.domain(t),"function"==typeof n?this.interpolator(n):this.range(n)}return this}const pg=Symbol("implicit");function gg(){var t=new InternMap,n=[],e=[],r=pg;function i(i){let o=t.get(i);if(void 0===o){if(r!==pg)return r;t.set(i,o=n.push(i)-1)}return e[o%e.length]}return i.domain=function(e){if(!arguments.length)return n.slice();n=[],t=new InternMap;for(const r of e)t.has(r)||t.set(r,n.push(r)-1);return i},i.range=function(t){return arguments.length?(e=Array.from(t),i):e.slice()},i.unknown=function(t){return arguments.length?(r=t,i):r},i.copy=function(){return gg(n,e).unknown(r)},hg.apply(i,arguments),i}function yg(){var t,n,e=gg().unknown(void 0),r=e.domain,i=e.range,o=0,a=1,u=!1,c=0,f=0,s=.5;function l(){var e=r().length,l=an&&(e=t,t=n,n=e),function(e){return Math.max(t,Math.min(n,e))}}(a[0],a[t-1])),r=t>2?Mg:wg,i=o=null,l}function l(n){return null==n||isNaN(n=+n)?e:(i||(i=r(a.map(t),u,c)))(t(f(n)))}return l.invert=function(e){return f(n((o||(o=r(u,a.map(t),Yr)))(e)))},l.domain=function(t){return arguments.length?(a=Array.from(t,_g),s()):a.slice()},l.range=function(t){return arguments.length?(u=Array.from(t),s()):u.slice()},l.rangeRound=function(t){return u=Array.from(t),c=Vr,s()},l.clamp=function(t){return arguments.length?(f=!!t||mg,s()):f!==mg},l.interpolate=function(t){return arguments.length?(c=t,s()):c},l.unknown=function(t){return arguments.length?(e=t,l):e},function(e,r){return t=e,n=r,s()}}function Sg(){return Ag()(mg,mg)}function Eg(n,e,r,i){var o,a=W(n,e,r);switch((i=Jc(null==i?",f":i)).type){case"s":var u=Math.max(Math.abs(n),Math.abs(e));return null!=i.precision||isNaN(o=lf(a,u))||(i.precision=o),t.formatPrefix(i,u);case"":case"e":case"g":case"p":case"r":null!=i.precision||isNaN(o=hf(a,Math.max(Math.abs(n),Math.abs(e))))||(i.precision=o-("e"===i.type));break;case"f":case"%":null!=i.precision||isNaN(o=sf(a))||(i.precision=o-2*("%"===i.type))}return t.format(i)}function Ng(t){var n=t.domain;return t.ticks=function(t){var e=n();return G(e[0],e[e.length-1],null==t?10:t)},t.tickFormat=function(t,e){var r=n();return Eg(r[0],r[r.length-1],null==t?10:t,e)},t.nice=function(e){null==e&&(e=10);var r,i,o=n(),a=0,u=o.length-1,c=o[a],f=o[u],s=10;for(f0;){if((i=V(c,f,e))===r)return o[a]=c,o[u]=f,n(o);if(i>0)c=Math.floor(c/i)*i,f=Math.ceil(f/i)*i;else{if(!(i<0))break;c=Math.ceil(c*i)/i,f=Math.floor(f*i)/i}r=i}return t},t}function kg(t,n){var e,r=0,i=(t=t.slice()).length-1,o=t[r],a=t[i];return a-t(-n,e)}function Fg(n){const e=n(Cg,Pg),r=e.domain;let i,o,a=10;function u(){return i=function(t){return t===Math.E?Math.log:10===t&&Math.log10||2===t&&Math.log2||(t=Math.log(t),n=>Math.log(n)/t)}(a),o=function(t){return 10===t?Dg:t===Math.E?Math.exp:n=>Math.pow(t,n)}(a),r()[0]<0?(i=Rg(i),o=Rg(o),n(zg,$g)):n(Cg,Pg),e}return e.base=function(t){return arguments.length?(a=+t,u()):a},e.domain=function(t){return arguments.length?(r(t),u()):r()},e.ticks=t=>{const n=r();let e=n[0],u=n[n.length-1];const c=u0){for(;l<=h;++l)for(f=1;fu)break;p.push(s)}}else for(;l<=h;++l)for(f=a-1;f>=1;--f)if(s=l>0?f/o(-l):f*o(l),!(su)break;p.push(s)}2*p.length{if(null==n&&(n=10),null==r&&(r=10===a?"s":","),"function"!=typeof r&&(a%1||null!=(r=Jc(r)).precision||(r.trim=!0),r=t.format(r)),n===1/0)return r;const u=Math.max(1,a*n/e.ticks().length);return t=>{let n=t/o(Math.round(i(t)));return n*ar(kg(r(),{floor:t=>o(Math.floor(i(t))),ceil:t=>o(Math.ceil(i(t)))})),e}function qg(t){return function(n){return Math.sign(n)*Math.log1p(Math.abs(n/t))}}function Ug(t){return function(n){return Math.sign(n)*Math.expm1(Math.abs(n))*t}}function Ig(t){var n=1,e=t(qg(n),Ug(n));return e.constant=function(e){return arguments.length?t(qg(n=+e),Ug(n)):n},Ng(e)}function Og(t){return function(n){return n<0?-Math.pow(-n,t):Math.pow(n,t)}}function Bg(t){return t<0?-Math.sqrt(-t):Math.sqrt(t)}function Yg(t){return t<0?-t*t:t*t}function Lg(t){var n=t(mg,mg),e=1;return n.exponent=function(n){return arguments.length?1===(e=+n)?t(mg,mg):.5===e?t(Bg,Yg):t(Og(e),Og(1/e)):e},Ng(n)}function jg(){var t=Lg(Ag());return t.copy=function(){return Tg(t,jg()).exponent(t.exponent())},hg.apply(t,arguments),t}function Hg(t){return Math.sign(t)*t*t}const Xg=new Date,Gg=new Date;function Vg(t,n,e,r){function i(n){return t(n=0===arguments.length?new Date:new Date(+n)),n}return i.floor=n=>(t(n=new Date(+n)),n),i.ceil=e=>(t(e=new Date(e-1)),n(e,1),t(e),e),i.round=t=>{const n=i(t),e=i.ceil(t);return t-n(n(t=new Date(+t),null==e?1:Math.floor(e)),t),i.range=(e,r,o)=>{const a=[];if(e=i.ceil(e),o=null==o?1:Math.floor(o),!(e0))return a;let u;do{a.push(u=new Date(+e)),n(e,o),t(e)}while(uVg((n=>{if(n>=n)for(;t(n),!e(n);)n.setTime(n-1)}),((t,r)=>{if(t>=t)if(r<0)for(;++r<=0;)for(;n(t,-1),!e(t););else for(;--r>=0;)for(;n(t,1),!e(t););})),e&&(i.count=(n,r)=>(Xg.setTime(+n),Gg.setTime(+r),t(Xg),t(Gg),Math.floor(e(Xg,Gg))),i.every=t=>(t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?n=>r(n)%t==0:n=>i.count(0,n)%t==0):i:null)),i}const Wg=Vg((()=>{}),((t,n)=>{t.setTime(+t+n)}),((t,n)=>n-t));Wg.every=t=>(t=Math.floor(t),isFinite(t)&&t>0?t>1?Vg((n=>{n.setTime(Math.floor(n/t)*t)}),((n,e)=>{n.setTime(+n+e*t)}),((n,e)=>(e-n)/t)):Wg:null);const Zg=Wg.range,Kg=1e3,Qg=6e4,Jg=36e5,ty=864e5,ny=6048e5,ey=2592e6,ry=31536e6,iy=Vg((t=>{t.setTime(t-t.getMilliseconds())}),((t,n)=>{t.setTime(+t+n*Kg)}),((t,n)=>(n-t)/Kg),(t=>t.getUTCSeconds())),oy=iy.range,ay=Vg((t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*Kg)}),((t,n)=>{t.setTime(+t+n*Qg)}),((t,n)=>(n-t)/Qg),(t=>t.getMinutes())),uy=ay.range,cy=Vg((t=>{t.setUTCSeconds(0,0)}),((t,n)=>{t.setTime(+t+n*Qg)}),((t,n)=>(n-t)/Qg),(t=>t.getUTCMinutes())),fy=cy.range,sy=Vg((t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*Kg-t.getMinutes()*Qg)}),((t,n)=>{t.setTime(+t+n*Jg)}),((t,n)=>(n-t)/Jg),(t=>t.getHours())),ly=sy.range,hy=Vg((t=>{t.setUTCMinutes(0,0,0)}),((t,n)=>{t.setTime(+t+n*Jg)}),((t,n)=>(n-t)/Jg),(t=>t.getUTCHours())),dy=hy.range,py=Vg((t=>t.setHours(0,0,0,0)),((t,n)=>t.setDate(t.getDate()+n)),((t,n)=>(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*Qg)/ty),(t=>t.getDate()-1)),gy=py.range,yy=Vg((t=>{t.setUTCHours(0,0,0,0)}),((t,n)=>{t.setUTCDate(t.getUTCDate()+n)}),((t,n)=>(n-t)/ty),(t=>t.getUTCDate()-1)),vy=yy.range,_y=Vg((t=>{t.setUTCHours(0,0,0,0)}),((t,n)=>{t.setUTCDate(t.getUTCDate()+n)}),((t,n)=>(n-t)/ty),(t=>Math.floor(t/ty))),by=_y.range;function my(t){return Vg((n=>{n.setDate(n.getDate()-(n.getDay()+7-t)%7),n.setHours(0,0,0,0)}),((t,n)=>{t.setDate(t.getDate()+7*n)}),((t,n)=>(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*Qg)/ny))}const xy=my(0),wy=my(1),My=my(2),Ty=my(3),Ay=my(4),Sy=my(5),Ey=my(6),Ny=xy.range,ky=wy.range,Cy=My.range,Py=Ty.range,zy=Ay.range,$y=Sy.range,Dy=Ey.range;function Ry(t){return Vg((n=>{n.setUTCDate(n.getUTCDate()-(n.getUTCDay()+7-t)%7),n.setUTCHours(0,0,0,0)}),((t,n)=>{t.setUTCDate(t.getUTCDate()+7*n)}),((t,n)=>(n-t)/ny))}const Fy=Ry(0),qy=Ry(1),Uy=Ry(2),Iy=Ry(3),Oy=Ry(4),By=Ry(5),Yy=Ry(6),Ly=Fy.range,jy=qy.range,Hy=Uy.range,Xy=Iy.range,Gy=Oy.range,Vy=By.range,Wy=Yy.range,Zy=Vg((t=>{t.setDate(1),t.setHours(0,0,0,0)}),((t,n)=>{t.setMonth(t.getMonth()+n)}),((t,n)=>n.getMonth()-t.getMonth()+12*(n.getFullYear()-t.getFullYear())),(t=>t.getMonth())),Ky=Zy.range,Qy=Vg((t=>{t.setUTCDate(1),t.setUTCHours(0,0,0,0)}),((t,n)=>{t.setUTCMonth(t.getUTCMonth()+n)}),((t,n)=>n.getUTCMonth()-t.getUTCMonth()+12*(n.getUTCFullYear()-t.getUTCFullYear())),(t=>t.getUTCMonth())),Jy=Qy.range,tv=Vg((t=>{t.setMonth(0,1),t.setHours(0,0,0,0)}),((t,n)=>{t.setFullYear(t.getFullYear()+n)}),((t,n)=>n.getFullYear()-t.getFullYear()),(t=>t.getFullYear()));tv.every=t=>isFinite(t=Math.floor(t))&&t>0?Vg((n=>{n.setFullYear(Math.floor(n.getFullYear()/t)*t),n.setMonth(0,1),n.setHours(0,0,0,0)}),((n,e)=>{n.setFullYear(n.getFullYear()+e*t)})):null;const nv=tv.range,ev=Vg((t=>{t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),((t,n)=>{t.setUTCFullYear(t.getUTCFullYear()+n)}),((t,n)=>n.getUTCFullYear()-t.getUTCFullYear()),(t=>t.getUTCFullYear()));ev.every=t=>isFinite(t=Math.floor(t))&&t>0?Vg((n=>{n.setUTCFullYear(Math.floor(n.getUTCFullYear()/t)*t),n.setUTCMonth(0,1),n.setUTCHours(0,0,0,0)}),((n,e)=>{n.setUTCFullYear(n.getUTCFullYear()+e*t)})):null;const rv=ev.range;function iv(t,n,e,i,o,a){const u=[[iy,1,Kg],[iy,5,5e3],[iy,15,15e3],[iy,30,3e4],[a,1,Qg],[a,5,3e5],[a,15,9e5],[a,30,18e5],[o,1,Jg],[o,3,108e5],[o,6,216e5],[o,12,432e5],[i,1,ty],[i,2,1728e5],[e,1,ny],[n,1,ey],[n,3,7776e6],[t,1,ry]];function c(n,e,i){const o=Math.abs(e-n)/i,a=r((([,,t])=>t)).right(u,o);if(a===u.length)return t.every(W(n/ry,e/ry,i));if(0===a)return Wg.every(Math.max(W(n,e,i),1));const[c,f]=u[o/u[a-1][2]=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:k_,s:C_,S:Zv,u:Kv,U:Qv,V:t_,w:n_,W:e_,x:null,X:null,y:r_,Y:o_,Z:u_,"%":N_},m={a:function(t){return a[t.getUTCDay()]},A:function(t){return o[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return u[t.getUTCMonth()]},c:null,d:c_,e:c_,f:d_,g:T_,G:S_,H:f_,I:s_,j:l_,L:h_,m:p_,M:g_,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:k_,s:C_,S:y_,u:v_,U:__,V:m_,w:x_,W:w_,x:null,X:null,y:M_,Y:A_,Z:E_,"%":N_},x={a:function(t,n,e){var r=d.exec(n.slice(e));return r?(t.w=p.get(r[0].toLowerCase()),e+r[0].length):-1},A:function(t,n,e){var r=l.exec(n.slice(e));return r?(t.w=h.get(r[0].toLowerCase()),e+r[0].length):-1},b:function(t,n,e){var r=v.exec(n.slice(e));return r?(t.m=_.get(r[0].toLowerCase()),e+r[0].length):-1},B:function(t,n,e){var r=g.exec(n.slice(e));return r?(t.m=y.get(r[0].toLowerCase()),e+r[0].length):-1},c:function(t,e,r){return T(t,n,e,r)},d:zv,e:zv,f:Uv,g:Nv,G:Ev,H:Dv,I:Dv,j:$v,L:qv,m:Pv,M:Rv,p:function(t,n,e){var r=f.exec(n.slice(e));return r?(t.p=s.get(r[0].toLowerCase()),e+r[0].length):-1},q:Cv,Q:Ov,s:Bv,S:Fv,u:Mv,U:Tv,V:Av,w:wv,W:Sv,x:function(t,n,r){return T(t,e,n,r)},X:function(t,n,e){return T(t,r,n,e)},y:Nv,Y:Ev,Z:kv,"%":Iv};function w(t,n){return function(e){var r,i,o,a=[],u=-1,c=0,f=t.length;for(e instanceof Date||(e=new Date(+e));++u53)return null;"w"in o||(o.w=1),"Z"in o?(i=(r=sv(lv(o.y,0,1))).getUTCDay(),r=i>4||0===i?qy.ceil(r):qy(r),r=yy.offset(r,7*(o.V-1)),o.y=r.getUTCFullYear(),o.m=r.getUTCMonth(),o.d=r.getUTCDate()+(o.w+6)%7):(i=(r=fv(lv(o.y,0,1))).getDay(),r=i>4||0===i?wy.ceil(r):wy(r),r=py.offset(r,7*(o.V-1)),o.y=r.getFullYear(),o.m=r.getMonth(),o.d=r.getDate()+(o.w+6)%7)}else("W"in o||"U"in o)&&("w"in o||(o.w="u"in o?o.u%7:"W"in o?1:0),i="Z"in o?sv(lv(o.y,0,1)).getUTCDay():fv(lv(o.y,0,1)).getDay(),o.m=0,o.d="W"in o?(o.w+6)%7+7*o.W-(i+5)%7:o.w+7*o.U-(i+6)%7);return"Z"in o?(o.H+=o.Z/100|0,o.M+=o.Z%100,sv(o)):fv(o)}}function T(t,n,e,r){for(var i,o,a=0,u=n.length,c=e.length;a=c)return-1;if(37===(i=n.charCodeAt(a++))){if(i=n.charAt(a++),!(o=x[i in pv?n.charAt(a++):i])||(r=o(t,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}return b.x=w(e,b),b.X=w(r,b),b.c=w(n,b),m.x=w(e,m),m.X=w(r,m),m.c=w(n,m),{format:function(t){var n=w(t+="",b);return n.toString=function(){return t},n},parse:function(t){var n=M(t+="",!1);return n.toString=function(){return t},n},utcFormat:function(t){var n=w(t+="",m);return n.toString=function(){return t},n},utcParse:function(t){var n=M(t+="",!0);return n.toString=function(){return t},n}}}var dv,pv={"-":"",_:" ",0:"0"},gv=/^\s*\d+/,yv=/^%/,vv=/[\\^$*+?|[\]().{}]/g;function _v(t,n,e){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o[t.toLowerCase(),n])))}function wv(t,n,e){var r=gv.exec(n.slice(e,e+1));return r?(t.w=+r[0],e+r[0].length):-1}function Mv(t,n,e){var r=gv.exec(n.slice(e,e+1));return r?(t.u=+r[0],e+r[0].length):-1}function Tv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.U=+r[0],e+r[0].length):-1}function Av(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.V=+r[0],e+r[0].length):-1}function Sv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.W=+r[0],e+r[0].length):-1}function Ev(t,n,e){var r=gv.exec(n.slice(e,e+4));return r?(t.y=+r[0],e+r[0].length):-1}function Nv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),e+r[0].length):-1}function kv(t,n,e){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(n.slice(e,e+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),e+r[0].length):-1}function Cv(t,n,e){var r=gv.exec(n.slice(e,e+1));return r?(t.q=3*r[0]-3,e+r[0].length):-1}function Pv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.m=r[0]-1,e+r[0].length):-1}function zv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.d=+r[0],e+r[0].length):-1}function $v(t,n,e){var r=gv.exec(n.slice(e,e+3));return r?(t.m=0,t.d=+r[0],e+r[0].length):-1}function Dv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.H=+r[0],e+r[0].length):-1}function Rv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.M=+r[0],e+r[0].length):-1}function Fv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.S=+r[0],e+r[0].length):-1}function qv(t,n,e){var r=gv.exec(n.slice(e,e+3));return r?(t.L=+r[0],e+r[0].length):-1}function Uv(t,n,e){var r=gv.exec(n.slice(e,e+6));return r?(t.L=Math.floor(r[0]/1e3),e+r[0].length):-1}function Iv(t,n,e){var r=yv.exec(n.slice(e,e+1));return r?e+r[0].length:-1}function Ov(t,n,e){var r=gv.exec(n.slice(e));return r?(t.Q=+r[0],e+r[0].length):-1}function Bv(t,n,e){var r=gv.exec(n.slice(e));return r?(t.s=+r[0],e+r[0].length):-1}function Yv(t,n){return _v(t.getDate(),n,2)}function Lv(t,n){return _v(t.getHours(),n,2)}function jv(t,n){return _v(t.getHours()%12||12,n,2)}function Hv(t,n){return _v(1+py.count(tv(t),t),n,3)}function Xv(t,n){return _v(t.getMilliseconds(),n,3)}function Gv(t,n){return Xv(t,n)+"000"}function Vv(t,n){return _v(t.getMonth()+1,n,2)}function Wv(t,n){return _v(t.getMinutes(),n,2)}function Zv(t,n){return _v(t.getSeconds(),n,2)}function Kv(t){var n=t.getDay();return 0===n?7:n}function Qv(t,n){return _v(xy.count(tv(t)-1,t),n,2)}function Jv(t){var n=t.getDay();return n>=4||0===n?Ay(t):Ay.ceil(t)}function t_(t,n){return t=Jv(t),_v(Ay.count(tv(t),t)+(4===tv(t).getDay()),n,2)}function n_(t){return t.getDay()}function e_(t,n){return _v(wy.count(tv(t)-1,t),n,2)}function r_(t,n){return _v(t.getFullYear()%100,n,2)}function i_(t,n){return _v((t=Jv(t)).getFullYear()%100,n,2)}function o_(t,n){return _v(t.getFullYear()%1e4,n,4)}function a_(t,n){var e=t.getDay();return _v((t=e>=4||0===e?Ay(t):Ay.ceil(t)).getFullYear()%1e4,n,4)}function u_(t){var n=t.getTimezoneOffset();return(n>0?"-":(n*=-1,"+"))+_v(n/60|0,"0",2)+_v(n%60,"0",2)}function c_(t,n){return _v(t.getUTCDate(),n,2)}function f_(t,n){return _v(t.getUTCHours(),n,2)}function s_(t,n){return _v(t.getUTCHours()%12||12,n,2)}function l_(t,n){return _v(1+yy.count(ev(t),t),n,3)}function h_(t,n){return _v(t.getUTCMilliseconds(),n,3)}function d_(t,n){return h_(t,n)+"000"}function p_(t,n){return _v(t.getUTCMonth()+1,n,2)}function g_(t,n){return _v(t.getUTCMinutes(),n,2)}function y_(t,n){return _v(t.getUTCSeconds(),n,2)}function v_(t){var n=t.getUTCDay();return 0===n?7:n}function __(t,n){return _v(Fy.count(ev(t)-1,t),n,2)}function b_(t){var n=t.getUTCDay();return n>=4||0===n?Oy(t):Oy.ceil(t)}function m_(t,n){return t=b_(t),_v(Oy.count(ev(t),t)+(4===ev(t).getUTCDay()),n,2)}function x_(t){return t.getUTCDay()}function w_(t,n){return _v(qy.count(ev(t)-1,t),n,2)}function M_(t,n){return _v(t.getUTCFullYear()%100,n,2)}function T_(t,n){return _v((t=b_(t)).getUTCFullYear()%100,n,2)}function A_(t,n){return _v(t.getUTCFullYear()%1e4,n,4)}function S_(t,n){var e=t.getUTCDay();return _v((t=e>=4||0===e?Oy(t):Oy.ceil(t)).getUTCFullYear()%1e4,n,4)}function E_(){return"+0000"}function N_(){return"%"}function k_(t){return+t}function C_(t){return Math.floor(+t/1e3)}function P_(n){return dv=hv(n),t.timeFormat=dv.format,t.timeParse=dv.parse,t.utcFormat=dv.utcFormat,t.utcParse=dv.utcParse,dv}t.timeFormat=void 0,t.timeParse=void 0,t.utcFormat=void 0,t.utcParse=void 0,P_({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});var z_="%Y-%m-%dT%H:%M:%S.%LZ";var $_=Date.prototype.toISOString?function(t){return t.toISOString()}:t.utcFormat(z_),D_=$_;var R_=+new Date("2000-01-01T00:00:00.000Z")?function(t){var n=new Date(t);return isNaN(n)?null:n}:t.utcParse(z_),F_=R_;function q_(t){return new Date(t)}function U_(t){return t instanceof Date?+t:+new Date(+t)}function I_(t,n,e,r,i,o,a,u,c,f){var s=Sg(),l=s.invert,h=s.domain,d=f(".%L"),p=f(":%S"),g=f("%I:%M"),y=f("%I %p"),v=f("%a %d"),_=f("%b %d"),b=f("%B"),m=f("%Y");function x(t){return(c(t)Fr(t[t.length-1]),rb=new Array(3).concat("d8b365f5f5f55ab4ac","a6611adfc27d80cdc1018571","a6611adfc27df5f5f580cdc1018571","8c510ad8b365f6e8c3c7eae55ab4ac01665e","8c510ad8b365f6e8c3f5f5f5c7eae55ab4ac01665e","8c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e","8c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e","5430058c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e003c30","5430058c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e003c30").map(H_),ib=eb(rb),ob=new Array(3).concat("af8dc3f7f7f77fbf7b","7b3294c2a5cfa6dba0008837","7b3294c2a5cff7f7f7a6dba0008837","762a83af8dc3e7d4e8d9f0d37fbf7b1b7837","762a83af8dc3e7d4e8f7f7f7d9f0d37fbf7b1b7837","762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b7837","762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b7837","40004b762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b783700441b","40004b762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b783700441b").map(H_),ab=eb(ob),ub=new Array(3).concat("e9a3c9f7f7f7a1d76a","d01c8bf1b6dab8e1864dac26","d01c8bf1b6daf7f7f7b8e1864dac26","c51b7de9a3c9fde0efe6f5d0a1d76a4d9221","c51b7de9a3c9fde0eff7f7f7e6f5d0a1d76a4d9221","c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221","c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221","8e0152c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221276419","8e0152c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221276419").map(H_),cb=eb(ub),fb=new Array(3).concat("998ec3f7f7f7f1a340","5e3c99b2abd2fdb863e66101","5e3c99b2abd2f7f7f7fdb863e66101","542788998ec3d8daebfee0b6f1a340b35806","542788998ec3d8daebf7f7f7fee0b6f1a340b35806","5427888073acb2abd2d8daebfee0b6fdb863e08214b35806","5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b35806","2d004b5427888073acb2abd2d8daebfee0b6fdb863e08214b358067f3b08","2d004b5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b358067f3b08").map(H_),sb=eb(fb),lb=new Array(3).concat("ef8a62f7f7f767a9cf","ca0020f4a58292c5de0571b0","ca0020f4a582f7f7f792c5de0571b0","b2182bef8a62fddbc7d1e5f067a9cf2166ac","b2182bef8a62fddbc7f7f7f7d1e5f067a9cf2166ac","b2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac","b2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac","67001fb2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac053061","67001fb2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac053061").map(H_),hb=eb(lb),db=new Array(3).concat("ef8a62ffffff999999","ca0020f4a582bababa404040","ca0020f4a582ffffffbababa404040","b2182bef8a62fddbc7e0e0e09999994d4d4d","b2182bef8a62fddbc7ffffffe0e0e09999994d4d4d","b2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d","b2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d","67001fb2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d1a1a1a","67001fb2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d1a1a1a").map(H_),pb=eb(db),gb=new Array(3).concat("fc8d59ffffbf91bfdb","d7191cfdae61abd9e92c7bb6","d7191cfdae61ffffbfabd9e92c7bb6","d73027fc8d59fee090e0f3f891bfdb4575b4","d73027fc8d59fee090ffffbfe0f3f891bfdb4575b4","d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4","d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4","a50026d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4313695","a50026d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4313695").map(H_),yb=eb(gb),vb=new Array(3).concat("fc8d59ffffbf91cf60","d7191cfdae61a6d96a1a9641","d7191cfdae61ffffbfa6d96a1a9641","d73027fc8d59fee08bd9ef8b91cf601a9850","d73027fc8d59fee08bffffbfd9ef8b91cf601a9850","d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850","d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850","a50026d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850006837","a50026d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850006837").map(H_),_b=eb(vb),bb=new Array(3).concat("fc8d59ffffbf99d594","d7191cfdae61abdda42b83ba","d7191cfdae61ffffbfabdda42b83ba","d53e4ffc8d59fee08be6f59899d5943288bd","d53e4ffc8d59fee08bffffbfe6f59899d5943288bd","d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd","d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd","9e0142d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd5e4fa2","9e0142d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd5e4fa2").map(H_),mb=eb(bb),xb=new Array(3).concat("e5f5f999d8c92ca25f","edf8fbb2e2e266c2a4238b45","edf8fbb2e2e266c2a42ca25f006d2c","edf8fbccece699d8c966c2a42ca25f006d2c","edf8fbccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45006d2c00441b").map(H_),wb=eb(xb),Mb=new Array(3).concat("e0ecf49ebcda8856a7","edf8fbb3cde38c96c688419d","edf8fbb3cde38c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d810f7c4d004b").map(H_),Tb=eb(Mb),Ab=new Array(3).concat("e0f3dba8ddb543a2ca","f0f9e8bae4bc7bccc42b8cbe","f0f9e8bae4bc7bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe0868ac084081").map(H_),Sb=eb(Ab),Eb=new Array(3).concat("fee8c8fdbb84e34a33","fef0d9fdcc8afc8d59d7301f","fef0d9fdcc8afc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301fb300007f0000").map(H_),Nb=eb(Eb),kb=new Array(3).concat("ece2f0a6bddb1c9099","f6eff7bdc9e167a9cf02818a","f6eff7bdc9e167a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016c59014636").map(H_),Cb=eb(kb),Pb=new Array(3).concat("ece7f2a6bddb2b8cbe","f1eef6bdc9e174a9cf0570b0","f1eef6bdc9e174a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0045a8d023858").map(H_),zb=eb(Pb),$b=new Array(3).concat("e7e1efc994c7dd1c77","f1eef6d7b5d8df65b0ce1256","f1eef6d7b5d8df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125698004367001f").map(H_),Db=eb($b),Rb=new Array(3).concat("fde0ddfa9fb5c51b8a","feebe2fbb4b9f768a1ae017e","feebe2fbb4b9f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a017749006a").map(H_),Fb=eb(Rb),qb=new Array(3).concat("edf8b17fcdbb2c7fb8","ffffcca1dab441b6c4225ea8","ffffcca1dab441b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea8253494081d58").map(H_),Ub=eb(qb),Ib=new Array(3).concat("f7fcb9addd8e31a354","ffffccc2e69978c679238443","ffffccc2e69978c67931a354006837","ffffccd9f0a3addd8e78c67931a354006837","ffffccd9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443006837004529").map(H_),Ob=eb(Ib),Bb=new Array(3).concat("fff7bcfec44fd95f0e","ffffd4fed98efe9929cc4c02","ffffd4fed98efe9929d95f0e993404","ffffd4fee391fec44ffe9929d95f0e993404","ffffd4fee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c02993404662506").map(H_),Yb=eb(Bb),Lb=new Array(3).concat("ffeda0feb24cf03b20","ffffb2fecc5cfd8d3ce31a1c","ffffb2fecc5cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cbd0026800026").map(H_),jb=eb(Lb),Hb=new Array(3).concat("deebf79ecae13182bd","eff3ffbdd7e76baed62171b5","eff3ffbdd7e76baed63182bd08519c","eff3ffc6dbef9ecae16baed63182bd08519c","eff3ffc6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b508519c08306b").map(H_),Xb=eb(Hb),Gb=new Array(3).concat("e5f5e0a1d99b31a354","edf8e9bae4b374c476238b45","edf8e9bae4b374c47631a354006d2c","edf8e9c7e9c0a1d99b74c47631a354006d2c","edf8e9c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45006d2c00441b").map(H_),Vb=eb(Gb),Wb=new Array(3).concat("f0f0f0bdbdbd636363","f7f7f7cccccc969696525252","f7f7f7cccccc969696636363252525","f7f7f7d9d9d9bdbdbd969696636363252525","f7f7f7d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525000000").map(H_),Zb=eb(Wb),Kb=new Array(3).concat("efedf5bcbddc756bb1","f2f0f7cbc9e29e9ac86a51a3","f2f0f7cbc9e29e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a354278f3f007d").map(H_),Qb=eb(Kb),Jb=new Array(3).concat("fee0d2fc9272de2d26","fee5d9fcae91fb6a4acb181d","fee5d9fcae91fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181da50f1567000d").map(H_),tm=eb(Jb),nm=new Array(3).concat("fee6cefdae6be6550d","feeddefdbe85fd8d3cd94701","feeddefdbe85fd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d94801a636037f2704").map(H_),em=eb(nm);var rm=hi(Tr(300,.5,0),Tr(-240,.5,1)),im=hi(Tr(-100,.75,.35),Tr(80,1.5,.8)),om=hi(Tr(260,.75,.35),Tr(80,1.5,.8)),am=Tr();var um=Fe(),cm=Math.PI/3,fm=2*Math.PI/3;function sm(t){var n=t.length;return function(e){return t[Math.max(0,Math.min(n-1,Math.floor(e*n)))]}}var lm=sm(H_("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")),hm=sm(H_("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),dm=sm(H_("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),pm=sm(H_("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));function gm(t){return function(){return t}}const ym=Math.abs,vm=Math.atan2,_m=Math.cos,bm=Math.max,mm=Math.min,xm=Math.sin,wm=Math.sqrt,Mm=1e-12,Tm=Math.PI,Am=Tm/2,Sm=2*Tm;function Em(t){return t>=1?Am:t<=-1?-Am:Math.asin(t)}function Nm(t){let n=3;return t.digits=function(e){if(!arguments.length)return n;if(null==e)n=null;else{const t=Math.floor(e);if(!(t>=0))throw new RangeError(`invalid digits: ${e}`);n=t}return t},()=>new Ua(n)}function km(t){return t.innerRadius}function Cm(t){return t.outerRadius}function Pm(t){return t.startAngle}function zm(t){return t.endAngle}function $m(t){return t&&t.padAngle}function Dm(t,n,e,r,i,o,a){var u=t-e,c=n-r,f=(a?o:-o)/wm(u*u+c*c),s=f*c,l=-f*u,h=t+s,d=n+l,p=e+s,g=r+l,y=(h+p)/2,v=(d+g)/2,_=p-h,b=g-d,m=_*_+b*b,x=i-o,w=h*g-p*d,M=(b<0?-1:1)*wm(bm(0,x*x*m-w*w)),T=(w*b-_*M)/m,A=(-w*_-b*M)/m,S=(w*b+_*M)/m,E=(-w*_+b*M)/m,N=T-y,k=A-v,C=S-y,P=E-v;return N*N+k*k>C*C+P*P&&(T=S,A=E),{cx:T,cy:A,x01:-s,y01:-l,x11:T*(i/x-1),y11:A*(i/x-1)}}var Rm=Array.prototype.slice;function Fm(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}function qm(t){this._context=t}function Um(t){return new qm(t)}function Im(t){return t[0]}function Om(t){return t[1]}function Bm(t,n){var e=gm(!0),r=null,i=Um,o=null,a=Nm(u);function u(u){var c,f,s,l=(u=Fm(u)).length,h=!1;for(null==r&&(o=i(s=a())),c=0;c<=l;++c)!(c=l;--h)u.point(v[h],_[h]);u.lineEnd(),u.areaEnd()}y&&(v[s]=+t(d,s,f),_[s]=+n(d,s,f),u.point(r?+r(d,s,f):v[s],e?+e(d,s,f):_[s]))}if(p)return u=null,p+""||null}function s(){return Bm().defined(i).curve(a).context(o)}return t="function"==typeof t?t:void 0===t?Im:gm(+t),n="function"==typeof n?n:gm(void 0===n?0:+n),e="function"==typeof e?e:void 0===e?Om:gm(+e),f.x=function(n){return arguments.length?(t="function"==typeof n?n:gm(+n),r=null,f):t},f.x0=function(n){return arguments.length?(t="function"==typeof n?n:gm(+n),f):t},f.x1=function(t){return arguments.length?(r=null==t?null:"function"==typeof t?t:gm(+t),f):r},f.y=function(t){return arguments.length?(n="function"==typeof t?t:gm(+t),e=null,f):n},f.y0=function(t){return arguments.length?(n="function"==typeof t?t:gm(+t),f):n},f.y1=function(t){return arguments.length?(e=null==t?null:"function"==typeof t?t:gm(+t),f):e},f.lineX0=f.lineY0=function(){return s().x(t).y(n)},f.lineY1=function(){return s().x(t).y(e)},f.lineX1=function(){return s().x(r).y(n)},f.defined=function(t){return arguments.length?(i="function"==typeof t?t:gm(!!t),f):i},f.curve=function(t){return arguments.length?(a=t,null!=o&&(u=a(o)),f):a},f.context=function(t){return arguments.length?(null==t?o=u=null:u=a(o=t),f):o},f}function Lm(t,n){return nt?1:n>=t?0:NaN}function jm(t){return t}qm.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:this._context.lineTo(t,n)}}};var Hm=Gm(Um);function Xm(t){this._curve=t}function Gm(t){function n(n){return new Xm(t(n))}return n._curve=t,n}function Vm(t){var n=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t.curve=function(t){return arguments.length?n(Gm(t)):n()._curve},t}function Wm(){return Vm(Bm().curve(Hm))}function Zm(){var t=Ym().curve(Hm),n=t.curve,e=t.lineX0,r=t.lineX1,i=t.lineY0,o=t.lineY1;return t.angle=t.x,delete t.x,t.startAngle=t.x0,delete t.x0,t.endAngle=t.x1,delete t.x1,t.radius=t.y,delete t.y,t.innerRadius=t.y0,delete t.y0,t.outerRadius=t.y1,delete t.y1,t.lineStartAngle=function(){return Vm(e())},delete t.lineX0,t.lineEndAngle=function(){return Vm(r())},delete t.lineX1,t.lineInnerRadius=function(){return Vm(i())},delete t.lineY0,t.lineOuterRadius=function(){return Vm(o())},delete t.lineY1,t.curve=function(t){return arguments.length?n(Gm(t)):n()._curve},t}function Km(t,n){return[(n=+n)*Math.cos(t-=Math.PI/2),n*Math.sin(t)]}Xm.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},lineEnd:function(){this._curve.lineEnd()},point:function(t,n){this._curve.point(n*Math.sin(t),n*-Math.cos(t))}};class Qm{constructor(t,n){this._context=t,this._x=n}areaStart(){this._line=0}areaEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line}point(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:this._x?this._context.bezierCurveTo(this._x0=(this._x0+t)/2,this._y0,this._x0,n,t,n):this._context.bezierCurveTo(this._x0,this._y0=(this._y0+n)/2,t,this._y0,t,n)}this._x0=t,this._y0=n}}class Jm{constructor(t){this._context=t}lineStart(){this._point=0}lineEnd(){}point(t,n){if(t=+t,n=+n,0===this._point)this._point=1;else{const e=Km(this._x0,this._y0),r=Km(this._x0,this._y0=(this._y0+n)/2),i=Km(t,this._y0),o=Km(t,n);this._context.moveTo(...e),this._context.bezierCurveTo(...r,...i,...o)}this._x0=t,this._y0=n}}function tx(t){return new Qm(t,!0)}function nx(t){return new Qm(t,!1)}function ex(t){return new Jm(t)}function rx(t){return t.source}function ix(t){return t.target}function ox(t){let n=rx,e=ix,r=Im,i=Om,o=null,a=null,u=Nm(c);function c(){let c;const f=Rm.call(arguments),s=n.apply(this,f),l=e.apply(this,f);if(null==o&&(a=t(c=u())),a.lineStart(),f[0]=s,a.point(+r.apply(this,f),+i.apply(this,f)),f[0]=l,a.point(+r.apply(this,f),+i.apply(this,f)),a.lineEnd(),c)return a=null,c+""||null}return c.source=function(t){return arguments.length?(n=t,c):n},c.target=function(t){return arguments.length?(e=t,c):e},c.x=function(t){return arguments.length?(r="function"==typeof t?t:gm(+t),c):r},c.y=function(t){return arguments.length?(i="function"==typeof t?t:gm(+t),c):i},c.context=function(n){return arguments.length?(null==n?o=a=null:a=t(o=n),c):o},c}const ax=wm(3);var ux={draw(t,n){const e=.59436*wm(n+mm(n/28,.75)),r=e/2,i=r*ax;t.moveTo(0,e),t.lineTo(0,-e),t.moveTo(-i,-r),t.lineTo(i,r),t.moveTo(-i,r),t.lineTo(i,-r)}},cx={draw(t,n){const e=wm(n/Tm);t.moveTo(e,0),t.arc(0,0,e,0,Sm)}},fx={draw(t,n){const e=wm(n/5)/2;t.moveTo(-3*e,-e),t.lineTo(-e,-e),t.lineTo(-e,-3*e),t.lineTo(e,-3*e),t.lineTo(e,-e),t.lineTo(3*e,-e),t.lineTo(3*e,e),t.lineTo(e,e),t.lineTo(e,3*e),t.lineTo(-e,3*e),t.lineTo(-e,e),t.lineTo(-3*e,e),t.closePath()}};const sx=wm(1/3),lx=2*sx;var hx={draw(t,n){const e=wm(n/lx),r=e*sx;t.moveTo(0,-e),t.lineTo(r,0),t.lineTo(0,e),t.lineTo(-r,0),t.closePath()}},dx={draw(t,n){const e=.62625*wm(n);t.moveTo(0,-e),t.lineTo(e,0),t.lineTo(0,e),t.lineTo(-e,0),t.closePath()}},px={draw(t,n){const e=.87559*wm(n-mm(n/7,2));t.moveTo(-e,0),t.lineTo(e,0),t.moveTo(0,e),t.lineTo(0,-e)}},gx={draw(t,n){const e=wm(n),r=-e/2;t.rect(r,r,e,e)}},yx={draw(t,n){const e=.4431*wm(n);t.moveTo(e,e),t.lineTo(e,-e),t.lineTo(-e,-e),t.lineTo(-e,e),t.closePath()}};const vx=xm(Tm/10)/xm(7*Tm/10),_x=xm(Sm/10)*vx,bx=-_m(Sm/10)*vx;var mx={draw(t,n){const e=wm(.8908130915292852*n),r=_x*e,i=bx*e;t.moveTo(0,-e),t.lineTo(r,i);for(let n=1;n<5;++n){const o=Sm*n/5,a=_m(o),u=xm(o);t.lineTo(u*e,-a*e),t.lineTo(a*r-u*i,u*r+a*i)}t.closePath()}};const xx=wm(3);var wx={draw(t,n){const e=-wm(n/(3*xx));t.moveTo(0,2*e),t.lineTo(-xx*e,-e),t.lineTo(xx*e,-e),t.closePath()}};const Mx=wm(3);var Tx={draw(t,n){const e=.6824*wm(n),r=e/2,i=e*Mx/2;t.moveTo(0,-e),t.lineTo(i,r),t.lineTo(-i,r),t.closePath()}};const Ax=-.5,Sx=wm(3)/2,Ex=1/wm(12),Nx=3*(Ex/2+1);var kx={draw(t,n){const e=wm(n/Nx),r=e/2,i=e*Ex,o=r,a=e*Ex+e,u=-o,c=a;t.moveTo(r,i),t.lineTo(o,a),t.lineTo(u,c),t.lineTo(Ax*r-Sx*i,Sx*r+Ax*i),t.lineTo(Ax*o-Sx*a,Sx*o+Ax*a),t.lineTo(Ax*u-Sx*c,Sx*u+Ax*c),t.lineTo(Ax*r+Sx*i,Ax*i-Sx*r),t.lineTo(Ax*o+Sx*a,Ax*a-Sx*o),t.lineTo(Ax*u+Sx*c,Ax*c-Sx*u),t.closePath()}},Cx={draw(t,n){const e=.6189*wm(n-mm(n/6,1.7));t.moveTo(-e,-e),t.lineTo(e,e),t.moveTo(-e,e),t.lineTo(e,-e)}};const Px=[cx,fx,hx,gx,mx,wx,kx],zx=[cx,px,Cx,Tx,ux,yx,dx];function $x(){}function Dx(t,n,e){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+n)/6,(t._y0+4*t._y1+e)/6)}function Rx(t){this._context=t}function Fx(t){this._context=t}function qx(t){this._context=t}function Ux(t,n){this._basis=new Rx(t),this._beta=n}Rx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:Dx(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:Dx(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},Fx.prototype={areaStart:$x,areaEnd:$x,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x2=t,this._y2=n;break;case 1:this._point=2,this._x3=t,this._y3=n;break;case 2:this._point=3,this._x4=t,this._y4=n,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+n)/6);break;default:Dx(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},qx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var e=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+n)/6;this._line?this._context.lineTo(e,r):this._context.moveTo(e,r);break;case 3:this._point=4;default:Dx(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},Ux.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,n=this._y,e=t.length-1;if(e>0)for(var r,i=t[0],o=n[0],a=t[e]-i,u=n[e]-o,c=-1;++c<=e;)r=c/e,this._basis.point(this._beta*t[c]+(1-this._beta)*(i+r*a),this._beta*n[c]+(1-this._beta)*(o+r*u));this._x=this._y=null,this._basis.lineEnd()},point:function(t,n){this._x.push(+t),this._y.push(+n)}};var Ix=function t(n){function e(t){return 1===n?new Rx(t):new Ux(t,n)}return e.beta=function(n){return t(+n)},e}(.85);function Ox(t,n,e){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-n),t._y2+t._k*(t._y1-e),t._x2,t._y2)}function Bx(t,n){this._context=t,this._k=(1-n)/6}Bx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:Ox(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2,this._x1=t,this._y1=n;break;case 2:this._point=3;default:Ox(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Yx=function t(n){function e(t){return new Bx(t,n)}return e.tension=function(n){return t(+n)},e}(0);function Lx(t,n){this._context=t,this._k=(1-n)/6}Lx.prototype={areaStart:$x,areaEnd:$x,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:Ox(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var jx=function t(n){function e(t){return new Lx(t,n)}return e.tension=function(n){return t(+n)},e}(0);function Hx(t,n){this._context=t,this._k=(1-n)/6}Hx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:Ox(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Xx=function t(n){function e(t){return new Hx(t,n)}return e.tension=function(n){return t(+n)},e}(0);function Gx(t,n,e){var r=t._x1,i=t._y1,o=t._x2,a=t._y2;if(t._l01_a>Mm){var u=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,c=3*t._l01_a*(t._l01_a+t._l12_a);r=(r*u-t._x0*t._l12_2a+t._x2*t._l01_2a)/c,i=(i*u-t._y0*t._l12_2a+t._y2*t._l01_2a)/c}if(t._l23_a>Mm){var f=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,s=3*t._l23_a*(t._l23_a+t._l12_a);o=(o*f+t._x1*t._l23_2a-n*t._l12_2a)/s,a=(a*f+t._y1*t._l23_2a-e*t._l12_2a)/s}t._context.bezierCurveTo(r,i,o,a,t._x2,t._y2)}function Vx(t,n){this._context=t,this._alpha=n}Vx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3;default:Gx(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Wx=function t(n){function e(t){return n?new Vx(t,n):new Bx(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);function Zx(t,n){this._context=t,this._alpha=n}Zx.prototype={areaStart:$x,areaEnd:$x,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:Gx(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Kx=function t(n){function e(t){return n?new Zx(t,n):new Lx(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);function Qx(t,n){this._context=t,this._alpha=n}Qx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:Gx(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Jx=function t(n){function e(t){return n?new Qx(t,n):new Hx(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);function tw(t){this._context=t}function nw(t){return t<0?-1:1}function ew(t,n,e){var r=t._x1-t._x0,i=n-t._x1,o=(t._y1-t._y0)/(r||i<0&&-0),a=(e-t._y1)/(i||r<0&&-0),u=(o*i+a*r)/(r+i);return(nw(o)+nw(a))*Math.min(Math.abs(o),Math.abs(a),.5*Math.abs(u))||0}function rw(t,n){var e=t._x1-t._x0;return e?(3*(t._y1-t._y0)/e-n)/2:n}function iw(t,n,e){var r=t._x0,i=t._y0,o=t._x1,a=t._y1,u=(o-r)/3;t._context.bezierCurveTo(r+u,i+u*n,o-u,a-u*e,o,a)}function ow(t){this._context=t}function aw(t){this._context=new uw(t)}function uw(t){this._context=t}function cw(t){this._context=t}function fw(t){var n,e,r=t.length-1,i=new Array(r),o=new Array(r),a=new Array(r);for(i[0]=0,o[0]=2,a[0]=t[0]+2*t[1],n=1;n=0;--n)i[n]=(a[n]-i[n+1])/o[n];for(o[r-1]=(t[r]+i[r-1])/2,n=0;n1)for(var e,r,i,o=1,a=t[n[0]],u=a.length;o=0;)e[n]=n;return e}function dw(t,n){return t[n]}function pw(t){const n=[];return n.key=t,n}function gw(t){var n=t.map(yw);return hw(t).sort((function(t,e){return n[t]-n[e]}))}function yw(t){for(var n,e=-1,r=0,i=t.length,o=-1/0;++eo&&(o=n,r=e);return r}function vw(t){var n=t.map(_w);return hw(t).sort((function(t,e){return n[t]-n[e]}))}function _w(t){for(var n,e=0,r=-1,i=t.length;++r=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,n),this._context.lineTo(t,n);else{var e=this._x*(1-this._t)+t*this._t;this._context.lineTo(e,this._y),this._context.lineTo(e,n)}}this._x=t,this._y=n}};var bw=t=>()=>t;function mw(t,{sourceEvent:n,target:e,transform:r,dispatch:i}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:n,enumerable:!0,configurable:!0},target:{value:e,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:i}})}function xw(t,n,e){this.k=t,this.x=n,this.y=e}xw.prototype={constructor:xw,scale:function(t){return 1===t?this:new xw(this.k*t,this.x,this.y)},translate:function(t,n){return 0===t&0===n?this:new xw(this.k,this.x+this.k*t,this.y+this.k*n)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var ww=new xw(1,0,0);function Mw(t){for(;!t.__zoom;)if(!(t=t.parentNode))return ww;return t.__zoom}function Tw(t){t.stopImmediatePropagation()}function Aw(t){t.preventDefault(),t.stopImmediatePropagation()}function Sw(t){return!(t.ctrlKey&&"wheel"!==t.type||t.button)}function Ew(){var t=this;return t instanceof SVGElement?(t=t.ownerSVGElement||t).hasAttribute("viewBox")?[[(t=t.viewBox.baseVal).x,t.y],[t.x+t.width,t.y+t.height]]:[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]:[[0,0],[t.clientWidth,t.clientHeight]]}function Nw(){return this.__zoom||ww}function kw(t){return-t.deltaY*(1===t.deltaMode?.05:t.deltaMode?1:.002)*(t.ctrlKey?10:1)}function Cw(){return navigator.maxTouchPoints||"ontouchstart"in this}function Pw(t,n,e){var r=t.invertX(n[0][0])-e[0][0],i=t.invertX(n[1][0])-e[1][0],o=t.invertY(n[0][1])-e[0][1],a=t.invertY(n[1][1])-e[1][1];return t.translate(i>r?(r+i)/2:Math.min(0,r)||Math.max(0,i),a>o?(o+a)/2:Math.min(0,o)||Math.max(0,a))}Mw.prototype=xw.prototype,t.Adder=T,t.Delaunay=Lu,t.FormatSpecifier=tf,t.InternMap=InternMap,t.InternSet=InternSet,t.Node=Qd,t.Path=Ua,t.Voronoi=qu,t.ZoomTransform=xw,t.active=function(t,n){var e,r,i=t.__transition;if(i)for(r in n=null==n?null:n+"",i)if((e=i[r]).state>qi&&e.name===n)return new po([[t]],Zo,n,+r);return null},t.arc=function(){var t=km,n=Cm,e=gm(0),r=null,i=Pm,o=zm,a=$m,u=null,c=Nm(f);function f(){var f,s,l=+t.apply(this,arguments),h=+n.apply(this,arguments),d=i.apply(this,arguments)-Am,p=o.apply(this,arguments)-Am,g=ym(p-d),y=p>d;if(u||(u=f=c()),hMm)if(g>Sm-Mm)u.moveTo(h*_m(d),h*xm(d)),u.arc(0,0,h,d,p,!y),l>Mm&&(u.moveTo(l*_m(p),l*xm(p)),u.arc(0,0,l,p,d,y));else{var v,_,b=d,m=p,x=d,w=p,M=g,T=g,A=a.apply(this,arguments)/2,S=A>Mm&&(r?+r.apply(this,arguments):wm(l*l+h*h)),E=mm(ym(h-l)/2,+e.apply(this,arguments)),N=E,k=E;if(S>Mm){var C=Em(S/l*xm(A)),P=Em(S/h*xm(A));(M-=2*C)>Mm?(x+=C*=y?1:-1,w-=C):(M=0,x=w=(d+p)/2),(T-=2*P)>Mm?(b+=P*=y?1:-1,m-=P):(T=0,b=m=(d+p)/2)}var z=h*_m(b),$=h*xm(b),D=l*_m(w),R=l*xm(w);if(E>Mm){var F,q=h*_m(m),U=h*xm(m),I=l*_m(x),O=l*xm(x);if(g1?0:t<-1?Tm:Math.acos(t)}((B*L+Y*j)/(wm(B*B+Y*Y)*wm(L*L+j*j)))/2),X=wm(F[0]*F[0]+F[1]*F[1]);N=mm(E,(l-X)/(H-1)),k=mm(E,(h-X)/(H+1))}else N=k=0}T>Mm?k>Mm?(v=Dm(I,O,z,$,h,k,y),_=Dm(q,U,D,R,h,k,y),u.moveTo(v.cx+v.x01,v.cy+v.y01),kMm&&M>Mm?N>Mm?(v=Dm(D,R,q,U,l,-N,y),_=Dm(z,$,I,O,l,-N,y),u.lineTo(v.cx+v.x01,v.cy+v.y01),N=0))throw new RangeError("invalid r");let e=t.length;if(!((e=Math.floor(e))>=0))throw new RangeError("invalid length");if(!e||!n)return t;const r=y(n),i=t.slice();return r(t,i,0,e,1),r(i,t,0,e,1),r(t,i,0,e,1),t},t.blur2=l,t.blurImage=h,t.brush=function(){return wa(la)},t.brushSelection=function(t){var n=t.__brush;return n?n.dim.output(n.selection):null},t.brushX=function(){return wa(fa)},t.brushY=function(){return wa(sa)},t.buffer=function(t,n){return fetch(t,n).then(_c)},t.chord=function(){return za(!1,!1)},t.chordDirected=function(){return za(!0,!1)},t.chordTranspose=function(){return za(!1,!0)},t.cluster=function(){var t=Ld,n=1,e=1,r=!1;function i(i){var o,a=0;i.eachAfter((function(n){var e=n.children;e?(n.x=function(t){return t.reduce(jd,0)/t.length}(e),n.y=function(t){return 1+t.reduce(Hd,0)}(e)):(n.x=o?a+=t(n,o):0,n.y=0,o=n)}));var u=function(t){for(var n;n=t.children;)t=n[0];return t}(i),c=function(t){for(var n;n=t.children;)t=n[n.length-1];return t}(i),f=u.x-t(u,c)/2,s=c.x+t(c,u)/2;return i.eachAfter(r?function(t){t.x=(t.x-i.x)*n,t.y=(i.y-t.y)*e}:function(t){t.x=(t.x-f)/(s-f)*n,t.y=(1-(i.y?t.y/i.y:1))*e})}return i.separation=function(n){return arguments.length?(t=n,i):t},i.size=function(t){return arguments.length?(r=!1,n=+t[0],e=+t[1],i):r?null:[n,e]},i.nodeSize=function(t){return arguments.length?(r=!0,n=+t[0],e=+t[1],i):r?[n,e]:null},i},t.color=ze,t.contourDensity=function(){var t=fu,n=su,e=lu,r=960,i=500,o=20,a=2,u=3*o,c=r+2*u>>a,f=i+2*u>>a,s=Qa(20);function h(r){var i=new Float32Array(c*f),s=Math.pow(2,-a),h=-1;for(const o of r){var d=(t(o,++h,r)+u)*s,p=(n(o,h,r)+u)*s,g=+e(o,h,r);if(g&&d>=0&&d=0&&pt*r)))(n).map(((t,n)=>(t.value=+e[n],p(t))))}function p(t){return t.coordinates.forEach(g),t}function g(t){t.forEach(y)}function y(t){t.forEach(v)}function v(t){t[0]=t[0]*Math.pow(2,a)-u,t[1]=t[1]*Math.pow(2,a)-u}function _(){return c=r+2*(u=3*o)>>a,f=i+2*u>>a,d}return d.contours=function(t){var n=h(t),e=iu().size([c,f]),r=Math.pow(2,2*a),i=t=>{t=+t;var i=p(e.contour(n,t*r));return i.value=t,i};return Object.defineProperty(i,"max",{get:()=>J(n)/r}),i},d.x=function(n){return arguments.length?(t="function"==typeof n?n:Qa(+n),d):t},d.y=function(t){return arguments.length?(n="function"==typeof t?t:Qa(+t),d):n},d.weight=function(t){return arguments.length?(e="function"==typeof t?t:Qa(+t),d):e},d.size=function(t){if(!arguments.length)return[r,i];var n=+t[0],e=+t[1];if(!(n>=0&&e>=0))throw new Error("invalid size");return r=n,i=e,_()},d.cellSize=function(t){if(!arguments.length)return 1<=1))throw new Error("invalid cell size");return a=Math.floor(Math.log(t)/Math.LN2),_()},d.thresholds=function(t){return arguments.length?(s="function"==typeof t?t:Array.isArray(t)?Qa(Za.call(t)):Qa(t),d):s},d.bandwidth=function(t){if(!arguments.length)return Math.sqrt(o*(o+1));if(!((t=+t)>=0))throw new Error("invalid bandwidth");return o=(Math.sqrt(4*t*t+1)-1)/2,_()},d},t.contours=iu,t.count=v,t.create=function(t){return Zn(Yt(t).call(document.documentElement))},t.creator=Yt,t.cross=function(...t){const n="function"==typeof t[t.length-1]&&function(t){return n=>t(...n)}(t.pop()),e=(t=t.map(m)).map(_),r=t.length-1,i=new Array(r+1).fill(0),o=[];if(r<0||e.some(b))return o;for(;;){o.push(i.map(((n,e)=>t[e][n])));let a=r;for(;++i[a]===e[a];){if(0===a)return n?o.map(n):o;i[a--]=0}}},t.csv=wc,t.csvFormat=rc,t.csvFormatBody=ic,t.csvFormatRow=ac,t.csvFormatRows=oc,t.csvFormatValue=uc,t.csvParse=nc,t.csvParseRows=ec,t.cubehelix=Tr,t.cumsum=function(t,n){var e=0,r=0;return Float64Array.from(t,void 0===n?t=>e+=+t||0:i=>e+=+n(i,r++,t)||0)},t.curveBasis=function(t){return new Rx(t)},t.curveBasisClosed=function(t){return new Fx(t)},t.curveBasisOpen=function(t){return new qx(t)},t.curveBumpX=tx,t.curveBumpY=nx,t.curveBundle=Ix,t.curveCardinal=Yx,t.curveCardinalClosed=jx,t.curveCardinalOpen=Xx,t.curveCatmullRom=Wx,t.curveCatmullRomClosed=Kx,t.curveCatmullRomOpen=Jx,t.curveLinear=Um,t.curveLinearClosed=function(t){return new tw(t)},t.curveMonotoneX=function(t){return new ow(t)},t.curveMonotoneY=function(t){return new aw(t)},t.curveNatural=function(t){return new cw(t)},t.curveStep=function(t){return new sw(t,.5)},t.curveStepAfter=function(t){return new sw(t,1)},t.curveStepBefore=function(t){return new sw(t,0)},t.descending=e,t.deviation=w,t.difference=function(t,...n){t=new InternSet(t);for(const e of n)for(const n of e)t.delete(n);return t},t.disjoint=function(t,n){const e=n[Symbol.iterator](),r=new InternSet;for(const n of t){if(r.has(n))return!1;let t,i;for(;({value:t,done:i}=e.next())&&!i;){if(Object.is(n,t))return!1;r.add(t)}}return!0},t.dispatch=$t,t.drag=function(){var t,n,e,r,i=se,o=le,a=he,u=de,c={},f=$t("start","drag","end"),s=0,l=0;function h(t){t.on("mousedown.drag",d).filter(u).on("touchstart.drag",y).on("touchmove.drag",v,ee).on("touchend.drag touchcancel.drag",_).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function d(a,u){if(!r&&i.call(this,a,u)){var c=b(this,o.call(this,a,u),a,u,"mouse");c&&(Zn(a.view).on("mousemove.drag",p,re).on("mouseup.drag",g,re),ae(a.view),ie(a),e=!1,t=a.clientX,n=a.clientY,c("start",a))}}function p(r){if(oe(r),!e){var i=r.clientX-t,o=r.clientY-n;e=i*i+o*o>l}c.mouse("drag",r)}function g(t){Zn(t.view).on("mousemove.drag mouseup.drag",null),ue(t.view,e),oe(t),c.mouse("end",t)}function y(t,n){if(i.call(this,t,n)){var e,r,a=t.changedTouches,u=o.call(this,t,n),c=a.length;for(e=0;e+t,t.easePoly=wo,t.easePolyIn=mo,t.easePolyInOut=wo,t.easePolyOut=xo,t.easeQuad=_o,t.easeQuadIn=function(t){return t*t},t.easeQuadInOut=_o,t.easeQuadOut=function(t){return t*(2-t)},t.easeSin=Ao,t.easeSinIn=function(t){return 1==+t?1:1-Math.cos(t*To)},t.easeSinInOut=Ao,t.easeSinOut=function(t){return Math.sin(t*To)},t.every=function(t,n){if("function"!=typeof n)throw new TypeError("test is not a function");let e=-1;for(const r of t)if(!n(r,++e,t))return!1;return!0},t.extent=M,t.fcumsum=function(t,n){const e=new T;let r=-1;return Float64Array.from(t,void 0===n?t=>e.add(+t||0):i=>e.add(+n(i,++r,t)||0))},t.filter=function(t,n){if("function"!=typeof n)throw new TypeError("test is not a function");const e=[];let r=-1;for(const i of t)n(i,++r,t)&&e.push(i);return e},t.flatGroup=function(t,...n){return z(P(t,...n),n)},t.flatRollup=function(t,n,...e){return z(D(t,n,...e),e)},t.forceCenter=function(t,n){var e,r=1;function i(){var i,o,a=e.length,u=0,c=0;for(i=0;if+p||os+p||ac.index){var g=f-u.x-u.vx,y=s-u.y-u.vy,v=g*g+y*y;vt.r&&(t.r=t[n].r)}function c(){if(n){var r,i,o=n.length;for(e=new Array(o),r=0;r[u(t,n,r),t])));for(a=0,i=new Array(f);a=u)){(t.data!==n||t.next)&&(0===l&&(p+=(l=Uc(e))*l),0===h&&(p+=(h=Uc(e))*h),p(t=(Lc*t+jc)%Hc)/Hc}();function l(){h(),f.call("tick",n),e1?(null==e?u.delete(t):u.set(t,p(e)),n):u.get(t)},find:function(n,e,r){var i,o,a,u,c,f=0,s=t.length;for(null==r?r=1/0:r*=r,f=0;f1?(f.on(t,e),n):f.on(t)}}},t.forceX=function(t){var n,e,r,i=qc(.1);function o(t){for(var i,o=0,a=n.length;o=.12&&i<.234&&r>=-.425&&r<-.214?u:i>=.166&&i<.234&&r>=-.214&&r<-.115?c:a).invert(t)},s.stream=function(e){return t&&n===e?t:(r=[a.stream(n=e),u.stream(e),c.stream(e)],i=r.length,t={point:function(t,n){for(var e=-1;++ejs(r[0],r[1])&&(r[1]=i[1]),js(i[0],r[1])>js(r[0],r[1])&&(r[0]=i[0])):o.push(r=i);for(a=-1/0,n=0,r=o[e=o.length-1];n<=e;r=i,++n)i=o[n],(u=js(r[1],i[0]))>a&&(a=u,Wf=i[0],Kf=r[1])}return is=os=null,Wf===1/0||Zf===1/0?[[NaN,NaN],[NaN,NaN]]:[[Wf,Zf],[Kf,Qf]]},t.geoCentroid=function(t){ms=xs=ws=Ms=Ts=As=Ss=Es=0,Ns=new T,ks=new T,Cs=new T,Lf(t,Gs);var n=+Ns,e=+ks,r=+Cs,i=Ef(n,e,r);return i=0))throw new RangeError(`invalid digits: ${t}`);i=n}return null===n&&(r=new ed(i)),a},a.projection(t).digits(i).context(n)},t.geoProjection=yd,t.geoProjectionMutator=vd,t.geoRotation=ll,t.geoStereographic=function(){return yd(Bd).scale(250).clipAngle(142)},t.geoStereographicRaw=Bd,t.geoStream=Lf,t.geoTransform=function(t){return{stream:id(t)}},t.geoTransverseMercator=function(){var t=Ed(Yd),n=t.center,e=t.rotate;return t.center=function(t){return arguments.length?n([-t[1],t[0]]):[(t=n())[1],-t[0]]},t.rotate=function(t){return arguments.length?e([t[0],t[1],t.length>2?t[2]+90:90]):[(t=e())[0],t[1],t[2]-90]},e([0,0,90]).scale(159.155)},t.geoTransverseMercatorRaw=Yd,t.gray=function(t,n){return new ur(t,0,0,null==n?1:n)},t.greatest=ot,t.greatestIndex=function(t,e=n){if(1===e.length)return tt(t,e);let r,i=-1,o=-1;for(const n of t)++o,(i<0?0===e(n,n):e(n,r)>0)&&(r=n,i=o);return i},t.group=C,t.groupSort=function(t,e,r){return(2!==e.length?U($(t,e,r),(([t,e],[r,i])=>n(e,i)||n(t,r))):U(C(t,r),(([t,r],[i,o])=>e(r,o)||n(t,i)))).map((([t])=>t))},t.groups=P,t.hcl=dr,t.hierarchy=Gd,t.histogram=Q,t.hsl=He,t.html=Ec,t.image=function(t,n){return new Promise((function(e,r){var i=new Image;for(var o in n)i[o]=n[o];i.onerror=r,i.onload=function(){e(i)},i.src=t}))},t.index=function(t,...n){return F(t,k,R,n)},t.indexes=function(t,...n){return F(t,Array.from,R,n)},t.interpolate=Gr,t.interpolateArray=function(t,n){return(Ir(n)?Ur:Or)(t,n)},t.interpolateBasis=Er,t.interpolateBasisClosed=Nr,t.interpolateBlues=Xb,t.interpolateBrBG=ib,t.interpolateBuGn=wb,t.interpolateBuPu=Tb,t.interpolateCividis=function(t){return t=Math.max(0,Math.min(1,t)),"rgb("+Math.max(0,Math.min(255,Math.round(-4.54-t*(35.34-t*(2381.73-t*(6402.7-t*(7024.72-2710.57*t)))))))+", "+Math.max(0,Math.min(255,Math.round(32.49+t*(170.73+t*(52.82-t*(131.46-t*(176.58-67.37*t)))))))+", "+Math.max(0,Math.min(255,Math.round(81.24+t*(442.36-t*(2482.43-t*(6167.24-t*(6614.94-2475.67*t)))))))+")"},t.interpolateCool=om,t.interpolateCubehelix=li,t.interpolateCubehelixDefault=rm,t.interpolateCubehelixLong=hi,t.interpolateDate=Br,t.interpolateDiscrete=function(t){var n=t.length;return function(e){return t[Math.max(0,Math.min(n-1,Math.floor(e*n)))]}},t.interpolateGnBu=Sb,t.interpolateGreens=Vb,t.interpolateGreys=Zb,t.interpolateHcl=ci,t.interpolateHclLong=fi,t.interpolateHsl=oi,t.interpolateHslLong=ai,t.interpolateHue=function(t,n){var e=Pr(+t,+n);return function(t){var n=e(t);return n-360*Math.floor(n/360)}},t.interpolateInferno=dm,t.interpolateLab=function(t,n){var e=$r((t=ar(t)).l,(n=ar(n)).l),r=$r(t.a,n.a),i=$r(t.b,n.b),o=$r(t.opacity,n.opacity);return function(n){return t.l=e(n),t.a=r(n),t.b=i(n),t.opacity=o(n),t+""}},t.interpolateMagma=hm,t.interpolateNumber=Yr,t.interpolateNumberArray=Ur,t.interpolateObject=Lr,t.interpolateOrRd=Nb,t.interpolateOranges=em,t.interpolatePRGn=ab,t.interpolatePiYG=cb,t.interpolatePlasma=pm,t.interpolatePuBu=zb,t.interpolatePuBuGn=Cb,t.interpolatePuOr=sb,t.interpolatePuRd=Db,t.interpolatePurples=Qb,t.interpolateRainbow=function(t){(t<0||t>1)&&(t-=Math.floor(t));var n=Math.abs(t-.5);return am.h=360*t-100,am.s=1.5-1.5*n,am.l=.8-.9*n,am+""},t.interpolateRdBu=hb,t.interpolateRdGy=pb,t.interpolateRdPu=Fb,t.interpolateRdYlBu=yb,t.interpolateRdYlGn=_b,t.interpolateReds=tm,t.interpolateRgb=Dr,t.interpolateRgbBasis=Fr,t.interpolateRgbBasisClosed=qr,t.interpolateRound=Vr,t.interpolateSinebow=function(t){var n;return t=(.5-t)*Math.PI,um.r=255*(n=Math.sin(t))*n,um.g=255*(n=Math.sin(t+cm))*n,um.b=255*(n=Math.sin(t+fm))*n,um+""},t.interpolateSpectral=mb,t.interpolateString=Xr,t.interpolateTransformCss=ti,t.interpolateTransformSvg=ni,t.interpolateTurbo=function(t){return t=Math.max(0,Math.min(1,t)),"rgb("+Math.max(0,Math.min(255,Math.round(34.61+t*(1172.33-t*(10793.56-t*(33300.12-t*(38394.49-14825.05*t)))))))+", "+Math.max(0,Math.min(255,Math.round(23.31+t*(557.33+t*(1225.33-t*(3574.96-t*(1073.77+707.56*t)))))))+", "+Math.max(0,Math.min(255,Math.round(27.2+t*(3211.1-t*(15327.97-t*(27814-t*(22569.18-6838.66*t)))))))+")"},t.interpolateViridis=lm,t.interpolateWarm=im,t.interpolateYlGn=Ob,t.interpolateYlGnBu=Ub,t.interpolateYlOrBr=Yb,t.interpolateYlOrRd=jb,t.interpolateZoom=ri,t.interrupt=Gi,t.intersection=function(t,...n){t=new InternSet(t),n=n.map(vt);t:for(const e of t)for(const r of n)if(!r.has(e)){t.delete(e);continue t}return t},t.interval=function(t,n,e){var r=new Ei,i=n;return null==n?(r.restart(t,n,e),r):(r._restart=r.restart,r.restart=function(t,n,e){n=+n,e=null==e?Ai():+e,r._restart((function o(a){a+=i,r._restart(o,i+=n,e),t(a)}),n,e)},r.restart(t,n,e),r)},t.isoFormat=D_,t.isoParse=F_,t.json=function(t,n){return fetch(t,n).then(Tc)},t.lab=ar,t.lch=function(t,n,e,r){return 1===arguments.length?hr(t):new pr(e,n,t,null==r?1:r)},t.least=function(t,e=n){let r,i=!1;if(1===e.length){let o;for(const a of t){const t=e(a);(i?n(t,o)<0:0===n(t,t))&&(r=a,o=t,i=!0)}}else for(const n of t)(i?e(n,r)<0:0===e(n,n))&&(r=n,i=!0);return r},t.leastIndex=ht,t.line=Bm,t.lineRadial=Wm,t.link=ox,t.linkHorizontal=function(){return ox(tx)},t.linkRadial=function(){const t=ox(ex);return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t},t.linkVertical=function(){return ox(nx)},t.local=Qn,t.map=function(t,n){if("function"!=typeof t[Symbol.iterator])throw new TypeError("values is not iterable");if("function"!=typeof n)throw new TypeError("mapper is not a function");return Array.from(t,((e,r)=>n(e,r,t)))},t.matcher=Vt,t.max=J,t.maxIndex=tt,t.mean=function(t,n){let e=0,r=0;if(void 0===n)for(let n of t)null!=n&&(n=+n)>=n&&(++e,r+=n);else{let i=-1;for(let o of t)null!=(o=n(o,++i,t))&&(o=+o)>=o&&(++e,r+=o)}if(e)return r/e},t.median=function(t,n){return at(t,.5,n)},t.medianIndex=function(t,n){return ct(t,.5,n)},t.merge=ft,t.min=nt,t.minIndex=et,t.mode=function(t,n){const e=new InternMap;if(void 0===n)for(let n of t)null!=n&&n>=n&&e.set(n,(e.get(n)||0)+1);else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&i>=i&&e.set(i,(e.get(i)||0)+1)}let r,i=0;for(const[t,n]of e)n>i&&(i=n,r=t);return r},t.namespace=It,t.namespaces=Ut,t.nice=Z,t.now=Ai,t.pack=function(){var t=null,n=1,e=1,r=np;function i(i){const o=ap();return i.x=n/2,i.y=e/2,t?i.eachBefore(xp(t)).eachAfter(wp(r,.5,o)).eachBefore(Mp(1)):i.eachBefore(xp(mp)).eachAfter(wp(np,1,o)).eachAfter(wp(r,i.r/Math.min(n,e),o)).eachBefore(Mp(Math.min(n,e)/(2*i.r))),i}return i.radius=function(n){return arguments.length?(t=Jd(n),i):t},i.size=function(t){return arguments.length?(n=+t[0],e=+t[1],i):[n,e]},i.padding=function(t){return arguments.length?(r="function"==typeof t?t:ep(+t),i):r},i},t.packEnclose=function(t){return up(t,ap())},t.packSiblings=function(t){return bp(t,ap()),t},t.pairs=function(t,n=st){const e=[];let r,i=!1;for(const o of t)i&&e.push(n(r,o)),r=o,i=!0;return e},t.partition=function(){var t=1,n=1,e=0,r=!1;function i(i){var o=i.height+1;return i.x0=i.y0=e,i.x1=t,i.y1=n/o,i.eachBefore(function(t,n){return function(r){r.children&&Ap(r,r.x0,t*(r.depth+1)/n,r.x1,t*(r.depth+2)/n);var i=r.x0,o=r.y0,a=r.x1-e,u=r.y1-e;a0&&(d+=l);for(null!=n?p.sort((function(t,e){return n(g[t],g[e])})):null!=e&&p.sort((function(t,n){return e(a[t],a[n])})),u=0,f=d?(v-h*b)/d:0;u0?l*f:0)+b,g[c]={data:a[c],index:u,value:l,startAngle:y,endAngle:s,padAngle:_};return g}return a.value=function(n){return arguments.length?(t="function"==typeof n?n:gm(+n),a):t},a.sortValues=function(t){return arguments.length?(n=t,e=null,a):n},a.sort=function(t){return arguments.length?(e=t,n=null,a):e},a.startAngle=function(t){return arguments.length?(r="function"==typeof t?t:gm(+t),a):r},a.endAngle=function(t){return arguments.length?(i="function"==typeof t?t:gm(+t),a):i},a.padAngle=function(t){return arguments.length?(o="function"==typeof t?t:gm(+t),a):o},a},t.piecewise=di,t.pointRadial=Km,t.pointer=ne,t.pointers=function(t,n){return t.target&&(t=te(t),void 0===n&&(n=t.currentTarget),t=t.touches||[t]),Array.from(t,(t=>ne(t,n)))},t.polygonArea=function(t){for(var n,e=-1,r=t.length,i=t[r-1],o=0;++eu!=f>u&&a<(c-e)*(u-r)/(f-r)+e&&(s=!s),c=e,f=r;return s},t.polygonHull=function(t){if((e=t.length)<3)return null;var n,e,r=new Array(e),i=new Array(e);for(n=0;n=0;--n)f.push(t[r[o[n]][2]]);for(n=+u;n(n=1664525*n+1013904223|0,lg*(n>>>0))},t.randomLogNormal=Kp,t.randomLogistic=fg,t.randomNormal=Zp,t.randomPareto=ng,t.randomPoisson=sg,t.randomUniform=Vp,t.randomWeibull=ug,t.range=lt,t.rank=function(t,e=n){if("function"!=typeof t[Symbol.iterator])throw new TypeError("values is not iterable");let r=Array.from(t);const i=new Float64Array(r.length);2!==e.length&&(r=r.map(e),e=n);const o=(t,n)=>e(r[t],r[n]);let a,u;return(t=Uint32Array.from(r,((t,n)=>n))).sort(e===n?(t,n)=>O(r[t],r[n]):I(o)),t.forEach(((t,n)=>{const e=o(t,void 0===a?t:a);e>=0?((void 0===a||e>0)&&(a=t,u=n),i[t]=u):i[t]=NaN})),i},t.reduce=function(t,n,e){if("function"!=typeof n)throw new TypeError("reducer is not a function");const r=t[Symbol.iterator]();let i,o,a=-1;if(arguments.length<3){if(({done:i,value:e}=r.next()),i)return;++a}for(;({done:i,value:o}=r.next()),!i;)e=n(e,o,++a,t);return e},t.reverse=function(t){if("function"!=typeof t[Symbol.iterator])throw new TypeError("values is not iterable");return Array.from(t).reverse()},t.rgb=Fe,t.ribbon=function(){return Wa()},t.ribbonArrow=function(){return Wa(Va)},t.rollup=$,t.rollups=D,t.scaleBand=yg,t.scaleDiverging=function t(){var n=Ng(L_()(mg));return n.copy=function(){return B_(n,t())},dg.apply(n,arguments)},t.scaleDivergingLog=function t(){var n=Fg(L_()).domain([.1,1,10]);return n.copy=function(){return B_(n,t()).base(n.base())},dg.apply(n,arguments)},t.scaleDivergingPow=j_,t.scaleDivergingSqrt=function(){return j_.apply(null,arguments).exponent(.5)},t.scaleDivergingSymlog=function t(){var n=Ig(L_());return n.copy=function(){return B_(n,t()).constant(n.constant())},dg.apply(n,arguments)},t.scaleIdentity=function t(n){var e;function r(t){return null==t||isNaN(t=+t)?e:t}return r.invert=r,r.domain=r.range=function(t){return arguments.length?(n=Array.from(t,_g),r):n.slice()},r.unknown=function(t){return arguments.length?(e=t,r):e},r.copy=function(){return t(n).unknown(e)},n=arguments.length?Array.from(n,_g):[0,1],Ng(r)},t.scaleImplicit=pg,t.scaleLinear=function t(){var n=Sg();return n.copy=function(){return Tg(n,t())},hg.apply(n,arguments),Ng(n)},t.scaleLog=function t(){const n=Fg(Ag()).domain([1,10]);return n.copy=()=>Tg(n,t()).base(n.base()),hg.apply(n,arguments),n},t.scaleOrdinal=gg,t.scalePoint=function(){return vg(yg.apply(null,arguments).paddingInner(1))},t.scalePow=jg,t.scaleQuantile=function t(){var e,r=[],i=[],o=[];function a(){var t=0,n=Math.max(1,i.length);for(o=new Array(n-1);++t0?o[n-1]:r[0],n=i?[o[i-1],r]:[o[n-1],o[n]]},u.unknown=function(t){return arguments.length?(n=t,u):u},u.thresholds=function(){return o.slice()},u.copy=function(){return t().domain([e,r]).range(a).unknown(n)},hg.apply(Ng(u),arguments)},t.scaleRadial=function t(){var n,e=Sg(),r=[0,1],i=!1;function o(t){var r=function(t){return Math.sign(t)*Math.sqrt(Math.abs(t))}(e(t));return isNaN(r)?n:i?Math.round(r):r}return o.invert=function(t){return e.invert(Hg(t))},o.domain=function(t){return arguments.length?(e.domain(t),o):e.domain()},o.range=function(t){return arguments.length?(e.range((r=Array.from(t,_g)).map(Hg)),o):r.slice()},o.rangeRound=function(t){return o.range(t).round(!0)},o.round=function(t){return arguments.length?(i=!!t,o):i},o.clamp=function(t){return arguments.length?(e.clamp(t),o):e.clamp()},o.unknown=function(t){return arguments.length?(n=t,o):n},o.copy=function(){return t(e.domain(),r).round(i).clamp(e.clamp()).unknown(n)},hg.apply(o,arguments),Ng(o)},t.scaleSequential=function t(){var n=Ng(O_()(mg));return n.copy=function(){return B_(n,t())},dg.apply(n,arguments)},t.scaleSequentialLog=function t(){var n=Fg(O_()).domain([1,10]);return n.copy=function(){return B_(n,t()).base(n.base())},dg.apply(n,arguments)},t.scaleSequentialPow=Y_,t.scaleSequentialQuantile=function t(){var e=[],r=mg;function i(t){if(null!=t&&!isNaN(t=+t))return r((s(e,t,1)-1)/(e.length-1))}return i.domain=function(t){if(!arguments.length)return e.slice();e=[];for(let n of t)null==n||isNaN(n=+n)||e.push(n);return e.sort(n),i},i.interpolator=function(t){return arguments.length?(r=t,i):r},i.range=function(){return e.map(((t,n)=>r(n/(e.length-1))))},i.quantiles=function(t){return Array.from({length:t+1},((n,r)=>at(e,r/t)))},i.copy=function(){return t(r).domain(e)},dg.apply(i,arguments)},t.scaleSequentialSqrt=function(){return Y_.apply(null,arguments).exponent(.5)},t.scaleSequentialSymlog=function t(){var n=Ig(O_());return n.copy=function(){return B_(n,t()).constant(n.constant())},dg.apply(n,arguments)},t.scaleSqrt=function(){return jg.apply(null,arguments).exponent(.5)},t.scaleSymlog=function t(){var n=Ig(Ag());return n.copy=function(){return Tg(n,t()).constant(n.constant())},hg.apply(n,arguments)},t.scaleThreshold=function t(){var n,e=[.5],r=[0,1],i=1;function o(t){return null!=t&&t<=t?r[s(e,t,0,i)]:n}return o.domain=function(t){return arguments.length?(e=Array.from(t),i=Math.min(e.length,r.length-1),o):e.slice()},o.range=function(t){return arguments.length?(r=Array.from(t),i=Math.min(e.length,r.length-1),o):r.slice()},o.invertExtent=function(t){var n=r.indexOf(t);return[e[n-1],e[n]]},o.unknown=function(t){return arguments.length?(n=t,o):n},o.copy=function(){return t().domain(e).range(r).unknown(n)},hg.apply(o,arguments)},t.scaleTime=function(){return hg.apply(I_(uv,cv,tv,Zy,xy,py,sy,ay,iy,t.timeFormat).domain([new Date(2e3,0,1),new Date(2e3,0,2)]),arguments)},t.scaleUtc=function(){return hg.apply(I_(ov,av,ev,Qy,Fy,yy,hy,cy,iy,t.utcFormat).domain([Date.UTC(2e3,0,1),Date.UTC(2e3,0,2)]),arguments)},t.scan=function(t,n){const e=ht(t,n);return e<0?void 0:e},t.schemeAccent=G_,t.schemeBlues=Hb,t.schemeBrBG=rb,t.schemeBuGn=xb,t.schemeBuPu=Mb,t.schemeCategory10=X_,t.schemeDark2=V_,t.schemeGnBu=Ab,t.schemeGreens=Gb,t.schemeGreys=Wb,t.schemeOrRd=Eb,t.schemeOranges=nm,t.schemePRGn=ob,t.schemePaired=W_,t.schemePastel1=Z_,t.schemePastel2=K_,t.schemePiYG=ub,t.schemePuBu=Pb,t.schemePuBuGn=kb,t.schemePuOr=fb,t.schemePuRd=$b,t.schemePurples=Kb,t.schemeRdBu=lb,t.schemeRdGy=db,t.schemeRdPu=Rb,t.schemeRdYlBu=gb,t.schemeRdYlGn=vb,t.schemeReds=Jb,t.schemeSet1=Q_,t.schemeSet2=J_,t.schemeSet3=tb,t.schemeSpectral=bb,t.schemeTableau10=nb,t.schemeYlGn=Ib,t.schemeYlGnBu=qb,t.schemeYlOrBr=Bb,t.schemeYlOrRd=Lb,t.select=Zn,t.selectAll=function(t){return"string"==typeof t?new Vn([document.querySelectorAll(t)],[document.documentElement]):new Vn([Ht(t)],Gn)},t.selection=Wn,t.selector=jt,t.selectorAll=Gt,t.shuffle=dt,t.shuffler=pt,t.some=function(t,n){if("function"!=typeof n)throw new TypeError("test is not a function");let e=-1;for(const r of t)if(n(r,++e,t))return!0;return!1},t.sort=U,t.stack=function(){var t=gm([]),n=hw,e=lw,r=dw;function i(i){var o,a,u=Array.from(t.apply(this,arguments),pw),c=u.length,f=-1;for(const t of i)for(o=0,++f;o0)for(var e,r,i,o,a,u,c=0,f=t[n[0]].length;c0?(r[0]=o,r[1]=o+=i):i<0?(r[1]=a,r[0]=a+=i):(r[0]=0,r[1]=i)},t.stackOffsetExpand=function(t,n){if((r=t.length)>0){for(var e,r,i,o=0,a=t[0].length;o0){for(var e,r=0,i=t[n[0]],o=i.length;r0&&(r=(e=t[n[0]]).length)>0){for(var e,r,i,o=0,a=1;afunction(t){t=`${t}`;let n=t.length;zp(t,n-1)&&!zp(t,n-2)&&(t=t.slice(0,-1));return"/"===t[0]?t:`/${t}`}(t(n,e,r)))),e=n.map(Pp),i=new Set(n).add("");for(const t of e)i.has(t)||(i.add(t),n.push(t),e.push(Pp(t)),h.push(Np));d=(t,e)=>n[e],p=(t,n)=>e[n]}for(a=0,i=h.length;a=0&&(f=h[t]).data===Np;--t)f.data=null}if(u.parent=Sp,u.eachBefore((function(t){t.depth=t.parent.depth+1,--i})).eachBefore(Kd),u.parent=null,i>0)throw new Error("cycle");return u}return r.id=function(t){return arguments.length?(n=Jd(t),r):n},r.parentId=function(t){return arguments.length?(e=Jd(t),r):e},r.path=function(n){return arguments.length?(t=Jd(n),r):t},r},t.style=_n,t.subset=function(t,n){return _t(n,t)},t.sum=function(t,n){let e=0;if(void 0===n)for(let n of t)(n=+n)&&(e+=n);else{let r=-1;for(let i of t)(i=+n(i,++r,t))&&(e+=i)}return e},t.superset=_t,t.svg=Nc,t.symbol=function(t,n){let e=null,r=Nm(i);function i(){let i;if(e||(e=i=r()),t.apply(this,arguments).draw(e,+n.apply(this,arguments)),i)return e=null,i+""||null}return t="function"==typeof t?t:gm(t||cx),n="function"==typeof n?n:gm(void 0===n?64:+n),i.type=function(n){return arguments.length?(t="function"==typeof n?n:gm(n),i):t},i.size=function(t){return arguments.length?(n="function"==typeof t?t:gm(+t),i):n},i.context=function(t){return arguments.length?(e=null==t?null:t,i):e},i},t.symbolAsterisk=ux,t.symbolCircle=cx,t.symbolCross=fx,t.symbolDiamond=hx,t.symbolDiamond2=dx,t.symbolPlus=px,t.symbolSquare=gx,t.symbolSquare2=yx,t.symbolStar=mx,t.symbolTimes=Cx,t.symbolTriangle=wx,t.symbolTriangle2=Tx,t.symbolWye=kx,t.symbolX=Cx,t.symbols=Px,t.symbolsFill=Px,t.symbolsStroke=zx,t.text=mc,t.thresholdFreedmanDiaconis=function(t,n,e){const r=v(t),i=at(t,.75)-at(t,.25);return r&&i?Math.ceil((e-n)/(2*i*Math.pow(r,-1/3))):1},t.thresholdScott=function(t,n,e){const r=v(t),i=w(t);return r&&i?Math.ceil((e-n)*Math.cbrt(r)/(3.49*i)):1},t.thresholdSturges=K,t.tickFormat=Eg,t.tickIncrement=V,t.tickStep=W,t.ticks=G,t.timeDay=py,t.timeDays=gy,t.timeFormatDefaultLocale=P_,t.timeFormatLocale=hv,t.timeFriday=Sy,t.timeFridays=$y,t.timeHour=sy,t.timeHours=ly,t.timeInterval=Vg,t.timeMillisecond=Wg,t.timeMilliseconds=Zg,t.timeMinute=ay,t.timeMinutes=uy,t.timeMonday=wy,t.timeMondays=ky,t.timeMonth=Zy,t.timeMonths=Ky,t.timeSaturday=Ey,t.timeSaturdays=Dy,t.timeSecond=iy,t.timeSeconds=oy,t.timeSunday=xy,t.timeSundays=Ny,t.timeThursday=Ay,t.timeThursdays=zy,t.timeTickInterval=cv,t.timeTicks=uv,t.timeTuesday=My,t.timeTuesdays=Cy,t.timeWednesday=Ty,t.timeWednesdays=Py,t.timeWeek=xy,t.timeWeeks=Ny,t.timeYear=tv,t.timeYears=nv,t.timeout=$i,t.timer=Ni,t.timerFlush=ki,t.transition=go,t.transpose=gt,t.tree=function(){var t=$p,n=1,e=1,r=null;function i(i){var c=function(t){for(var n,e,r,i,o,a=new Up(t,0),u=[a];n=u.pop();)if(r=n._.children)for(n.children=new Array(o=r.length),i=o-1;i>=0;--i)u.push(e=n.children[i]=new Up(r[i],i)),e.parent=n;return(a.parent=new Up(null,0)).children=[a],a}(i);if(c.eachAfter(o),c.parent.m=-c.z,c.eachBefore(a),r)i.eachBefore(u);else{var f=i,s=i,l=i;i.eachBefore((function(t){t.xs.x&&(s=t),t.depth>l.depth&&(l=t)}));var h=f===s?1:t(f,s)/2,d=h-f.x,p=n/(s.x+h+d),g=e/(l.depth||1);i.eachBefore((function(t){t.x=(t.x+d)*p,t.y=t.depth*g}))}return i}function o(n){var e=n.children,r=n.parent.children,i=n.i?r[n.i-1]:null;if(e){!function(t){for(var n,e=0,r=0,i=t.children,o=i.length;--o>=0;)(n=i[o]).z+=e,n.m+=e,e+=n.s+(r+=n.c)}(n);var o=(e[0].z+e[e.length-1].z)/2;i?(n.z=i.z+t(n._,i._),n.m=n.z-o):n.z=o}else i&&(n.z=i.z+t(n._,i._));n.parent.A=function(n,e,r){if(e){for(var i,o=n,a=n,u=e,c=o.parent.children[0],f=o.m,s=a.m,l=u.m,h=c.m;u=Rp(u),o=Dp(o),u&&o;)c=Dp(c),(a=Rp(a)).a=n,(i=u.z+l-o.z-f+t(u._,o._))>0&&(Fp(qp(u,n,r),n,i),f+=i,s+=i),l+=u.m,f+=o.m,h+=c.m,s+=a.m;u&&!Rp(a)&&(a.t=u,a.m+=l-s),o&&!Dp(c)&&(c.t=o,c.m+=f-h,r=n)}return r}(n,i,n.parent.A||r[0])}function a(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function u(t){t.x*=n,t.y=t.depth*e}return i.separation=function(n){return arguments.length?(t=n,i):t},i.size=function(t){return arguments.length?(r=!1,n=+t[0],e=+t[1],i):r?null:[n,e]},i.nodeSize=function(t){return arguments.length?(r=!0,n=+t[0],e=+t[1],i):r?[n,e]:null},i},t.treemap=function(){var t=Yp,n=!1,e=1,r=1,i=[0],o=np,a=np,u=np,c=np,f=np;function s(t){return t.x0=t.y0=0,t.x1=e,t.y1=r,t.eachBefore(l),i=[0],n&&t.eachBefore(Tp),t}function l(n){var e=i[n.depth],r=n.x0+e,s=n.y0+e,l=n.x1-e,h=n.y1-e;l=e-1){var s=u[n];return s.x0=i,s.y0=o,s.x1=a,void(s.y1=c)}var l=f[n],h=r/2+l,d=n+1,p=e-1;for(;d>>1;f[g]c-o){var _=r?(i*v+a*y)/r:a;t(n,d,y,i,o,_,c),t(d,e,v,_,o,a,c)}else{var b=r?(o*v+c*y)/r:c;t(n,d,y,i,o,a,b),t(d,e,v,i,b,a,c)}}(0,c,t.value,n,e,r,i)},t.treemapDice=Ap,t.treemapResquarify=Lp,t.treemapSlice=Ip,t.treemapSliceDice=function(t,n,e,r,i){(1&t.depth?Ip:Ap)(t,n,e,r,i)},t.treemapSquarify=Yp,t.tsv=Mc,t.tsvFormat=lc,t.tsvFormatBody=hc,t.tsvFormatRow=pc,t.tsvFormatRows=dc,t.tsvFormatValue=gc,t.tsvParse=fc,t.tsvParseRows=sc,t.union=function(...t){const n=new InternSet;for(const e of t)for(const t of e)n.add(t);return n},t.unixDay=_y,t.unixDays=by,t.utcDay=yy,t.utcDays=vy,t.utcFriday=By,t.utcFridays=Vy,t.utcHour=hy,t.utcHours=dy,t.utcMillisecond=Wg,t.utcMilliseconds=Zg,t.utcMinute=cy,t.utcMinutes=fy,t.utcMonday=qy,t.utcMondays=jy,t.utcMonth=Qy,t.utcMonths=Jy,t.utcSaturday=Yy,t.utcSaturdays=Wy,t.utcSecond=iy,t.utcSeconds=oy,t.utcSunday=Fy,t.utcSundays=Ly,t.utcThursday=Oy,t.utcThursdays=Gy,t.utcTickInterval=av,t.utcTicks=ov,t.utcTuesday=Uy,t.utcTuesdays=Hy,t.utcWednesday=Iy,t.utcWednesdays=Xy,t.utcWeek=Fy,t.utcWeeks=Ly,t.utcYear=ev,t.utcYears=rv,t.variance=x,t.version="7.8.5",t.window=pn,t.xml=Sc,t.zip=function(){return gt(arguments)},t.zoom=function(){var t,n,e,r=Sw,i=Ew,o=Pw,a=kw,u=Cw,c=[0,1/0],f=[[-1/0,-1/0],[1/0,1/0]],s=250,l=ri,h=$t("start","zoom","end"),d=500,p=150,g=0,y=10;function v(t){t.property("__zoom",Nw).on("wheel.zoom",T,{passive:!1}).on("mousedown.zoom",A).on("dblclick.zoom",S).filter(u).on("touchstart.zoom",E).on("touchmove.zoom",N).on("touchend.zoom touchcancel.zoom",k).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function _(t,n){return(n=Math.max(c[0],Math.min(c[1],n)))===t.k?t:new xw(n,t.x,t.y)}function b(t,n,e){var r=n[0]-e[0]*t.k,i=n[1]-e[1]*t.k;return r===t.x&&i===t.y?t:new xw(t.k,r,i)}function m(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function x(t,n,e,r){t.on("start.zoom",(function(){w(this,arguments).event(r).start()})).on("interrupt.zoom end.zoom",(function(){w(this,arguments).event(r).end()})).tween("zoom",(function(){var t=this,o=arguments,a=w(t,o).event(r),u=i.apply(t,o),c=null==e?m(u):"function"==typeof e?e.apply(t,o):e,f=Math.max(u[1][0]-u[0][0],u[1][1]-u[0][1]),s=t.__zoom,h="function"==typeof n?n.apply(t,o):n,d=l(s.invert(c).concat(f/s.k),h.invert(c).concat(f/h.k));return function(t){if(1===t)t=h;else{var n=d(t),e=f/n[2];t=new xw(e,c[0]-n[0]*e,c[1]-n[1]*e)}a.zoom(null,t)}}))}function w(t,n,e){return!e&&t.__zooming||new M(t,n)}function M(t,n){this.that=t,this.args=n,this.active=0,this.sourceEvent=null,this.extent=i.apply(t,n),this.taps=0}function T(t,...n){if(r.apply(this,arguments)){var e=w(this,n).event(t),i=this.__zoom,u=Math.max(c[0],Math.min(c[1],i.k*Math.pow(2,a.apply(this,arguments)))),s=ne(t);if(e.wheel)e.mouse[0][0]===s[0]&&e.mouse[0][1]===s[1]||(e.mouse[1]=i.invert(e.mouse[0]=s)),clearTimeout(e.wheel);else{if(i.k===u)return;e.mouse=[s,i.invert(s)],Gi(this),e.start()}Aw(t),e.wheel=setTimeout((function(){e.wheel=null,e.end()}),p),e.zoom("mouse",o(b(_(i,u),e.mouse[0],e.mouse[1]),e.extent,f))}}function A(t,...n){if(!e&&r.apply(this,arguments)){var i=t.currentTarget,a=w(this,n,!0).event(t),u=Zn(t.view).on("mousemove.zoom",(function(t){if(Aw(t),!a.moved){var n=t.clientX-s,e=t.clientY-l;a.moved=n*n+e*e>g}a.event(t).zoom("mouse",o(b(a.that.__zoom,a.mouse[0]=ne(t,i),a.mouse[1]),a.extent,f))}),!0).on("mouseup.zoom",(function(t){u.on("mousemove.zoom mouseup.zoom",null),ue(t.view,a.moved),Aw(t),a.event(t).end()}),!0),c=ne(t,i),s=t.clientX,l=t.clientY;ae(t.view),Tw(t),a.mouse=[c,this.__zoom.invert(c)],Gi(this),a.start()}}function S(t,...n){if(r.apply(this,arguments)){var e=this.__zoom,a=ne(t.changedTouches?t.changedTouches[0]:t,this),u=e.invert(a),c=e.k*(t.shiftKey?.5:2),l=o(b(_(e,c),a,u),i.apply(this,n),f);Aw(t),s>0?Zn(this).transition().duration(s).call(x,l,a,t):Zn(this).call(v.transform,l,a,t)}}function E(e,...i){if(r.apply(this,arguments)){var o,a,u,c,f=e.touches,s=f.length,l=w(this,i,e.changedTouches.length===s).event(e);for(Tw(e),a=0;an?1:t>=n?0:NaN}function e(t,n){return null==t||null==n?NaN:nt?1:n>=t?0:NaN}function r(t){let r,o,a;function u(t,n,e=0,i=t.length){if(e>>1;o(t[r],n)<0?e=r+1:i=r}while(en(t(e),r),a=(n,e)=>t(n)-e):(r=t===n||t===e?t:i,o=t,a=t),{left:u,center:function(t,n,e=0,r=t.length){const i=u(t,n,e,r-1);return i>e&&a(t[i-1],n)>-a(t[i],n)?i-1:i},right:function(t,n,e=0,i=t.length){if(e>>1;o(t[r],n)<=0?e=r+1:i=r}while(e{n(t,e,(r<<=2)+0,(i<<=2)+0,o<<=2),n(t,e,r+1,i+1,o),n(t,e,r+2,i+2,o),n(t,e,r+3,i+3,o)}}));function d(t){return function(n,e,r=e){if(!((e=+e)>=0))throw new RangeError("invalid rx");if(!((r=+r)>=0))throw new RangeError("invalid ry");let{data:i,width:o,height:a}=n;if(!((o=Math.floor(o))>=0))throw new RangeError("invalid width");if(!((a=Math.floor(void 0!==a?a:i.length/o))>=0))throw new RangeError("invalid height");if(!o||!a||!e&&!r)return n;const u=e&&t(e),c=r&&t(r),f=i.slice();return u&&c?(p(u,f,i,o,a),p(u,i,f,o,a),p(u,f,i,o,a),g(c,i,f,o,a),g(c,f,i,o,a),g(c,i,f,o,a)):u?(p(u,i,f,o,a),p(u,f,i,o,a),p(u,i,f,o,a)):c&&(g(c,i,f,o,a),g(c,f,i,o,a),g(c,i,f,o,a)),n}}function p(t,n,e,r,i){for(let o=0,a=r*i;o{if(!((o-=a)>=i))return;let u=t*r[i];const c=a*t;for(let t=i,n=i+c;t{if(!((a-=u)>=o))return;let c=n*i[o];const f=u*n,s=f+u;for(let t=o,n=o+f;t=n&&++e;else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&(i=+i)>=i&&++e}return e}function _(t){return 0|t.length}function b(t){return!(t>0)}function m(t){return"object"!=typeof t||"length"in t?t:Array.from(t)}function x(t,n){let e,r=0,i=0,o=0;if(void 0===n)for(let n of t)null!=n&&(n=+n)>=n&&(e=n-i,i+=e/++r,o+=e*(n-i));else{let a=-1;for(let u of t)null!=(u=n(u,++a,t))&&(u=+u)>=u&&(e=u-i,i+=e/++r,o+=e*(u-i))}if(r>1)return o/(r-1)}function w(t,n){const e=x(t,n);return e?Math.sqrt(e):e}function M(t,n){let e,r;if(void 0===n)for(const n of t)null!=n&&(void 0===e?n>=n&&(e=r=n):(e>n&&(e=n),r=o&&(e=r=o):(e>o&&(e=o),r0){for(o=t[--i];i>0&&(n=o,e=t[--i],o=n+e,r=e-(o-n),!r););i>0&&(r<0&&t[i-1]<0||r>0&&t[i-1]>0)&&(e=2*r,n=o+e,e==n-o&&(o=n))}return o}}class InternMap extends Map{constructor(t,n=N){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:n}}),null!=t)for(const[n,e]of t)this.set(n,e)}get(t){return super.get(A(this,t))}has(t){return super.has(A(this,t))}set(t,n){return super.set(S(this,t),n)}delete(t){return super.delete(E(this,t))}}class InternSet extends Set{constructor(t,n=N){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:n}}),null!=t)for(const n of t)this.add(n)}has(t){return super.has(A(this,t))}add(t){return super.add(S(this,t))}delete(t){return super.delete(E(this,t))}}function A({_intern:t,_key:n},e){const r=n(e);return t.has(r)?t.get(r):e}function S({_intern:t,_key:n},e){const r=n(e);return t.has(r)?t.get(r):(t.set(r,e),e)}function E({_intern:t,_key:n},e){const r=n(e);return t.has(r)&&(e=t.get(r),t.delete(r)),e}function N(t){return null!==t&&"object"==typeof t?t.valueOf():t}function k(t){return t}function C(t,...n){return F(t,k,k,n)}function P(t,...n){return F(t,Array.from,k,n)}function z(t,n){for(let e=1,r=n.length;et.pop().map((([n,e])=>[...t,n,e]))));return t}function $(t,n,...e){return F(t,k,n,e)}function D(t,n,...e){return F(t,Array.from,n,e)}function R(t){if(1!==t.length)throw new Error("duplicate key");return t[0]}function F(t,n,e,r){return function t(i,o){if(o>=r.length)return e(i);const a=new InternMap,u=r[o++];let c=-1;for(const t of i){const n=u(t,++c,i),e=a.get(n);e?e.push(t):a.set(n,[t])}for(const[n,e]of a)a.set(n,t(e,o));return n(a)}(t,0)}function q(t,n){return Array.from(n,(n=>t[n]))}function U(t,...n){if("function"!=typeof t[Symbol.iterator])throw new TypeError("values is not iterable");t=Array.from(t);let[e]=n;if(e&&2!==e.length||n.length>1){const r=Uint32Array.from(t,((t,n)=>n));return n.length>1?(n=n.map((n=>t.map(n))),r.sort(((t,e)=>{for(const r of n){const n=O(r[t],r[e]);if(n)return n}}))):(e=t.map(e),r.sort(((t,n)=>O(e[t],e[n])))),q(t,r)}return t.sort(I(e))}function I(t=n){if(t===n)return O;if("function"!=typeof t)throw new TypeError("compare is not a function");return(n,e)=>{const r=t(n,e);return r||0===r?r:(0===t(e,e))-(0===t(n,n))}}function O(t,n){return(null==t||!(t>=t))-(null==n||!(n>=n))||(tn?1:0)}var B=Array.prototype.slice;function Y(t){return()=>t}const L=Math.sqrt(50),j=Math.sqrt(10),H=Math.sqrt(2);function X(t,n,e){const r=(n-t)/Math.max(0,e),i=Math.floor(Math.log10(r)),o=r/Math.pow(10,i),a=o>=L?10:o>=j?5:o>=H?2:1;let u,c,f;return i<0?(f=Math.pow(10,-i)/a,u=Math.round(t*f),c=Math.round(n*f),u/fn&&--c,f=-f):(f=Math.pow(10,i)*a,u=Math.round(t/f),c=Math.round(n/f),u*fn&&--c),c0))return[];if((t=+t)===(n=+n))return[t];const r=n=i))return[];const u=o-i+1,c=new Array(u);if(r)if(a<0)for(let t=0;t0?(t=Math.floor(t/i)*i,n=Math.ceil(n/i)*i):i<0&&(t=Math.ceil(t*i)/i,n=Math.floor(n*i)/i),r=i}}function K(t){return Math.max(1,Math.ceil(Math.log(v(t))/Math.LN2)+1)}function Q(){var t=k,n=M,e=K;function r(r){Array.isArray(r)||(r=Array.from(r));var i,o,a,u=r.length,c=new Array(u);for(i=0;i=h)if(t>=h&&n===M){const t=V(l,h,e);isFinite(t)&&(t>0?h=(Math.floor(h/t)+1)*t:t<0&&(h=(Math.ceil(h*-t)+1)/-t))}else d.pop()}for(var p=d.length,g=0,y=p;d[g]<=l;)++g;for(;d[y-1]>h;)--y;(g||y0?d[i-1]:l,v.x1=i0)for(i=0;i=n)&&(e=n);else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&(e=i)&&(e=i)}return e}function tt(t,n){let e,r=-1,i=-1;if(void 0===n)for(const n of t)++i,null!=n&&(e=n)&&(e=n,r=i);else for(let o of t)null!=(o=n(o,++i,t))&&(e=o)&&(e=o,r=i);return r}function nt(t,n){let e;if(void 0===n)for(const n of t)null!=n&&(e>n||void 0===e&&n>=n)&&(e=n);else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&(e>i||void 0===e&&i>=i)&&(e=i)}return e}function et(t,n){let e,r=-1,i=-1;if(void 0===n)for(const n of t)++i,null!=n&&(e>n||void 0===e&&n>=n)&&(e=n,r=i);else for(let o of t)null!=(o=n(o,++i,t))&&(e>o||void 0===e&&o>=o)&&(e=o,r=i);return r}function rt(t,n,e=0,r=1/0,i){if(n=Math.floor(n),e=Math.floor(Math.max(0,e)),r=Math.floor(Math.min(t.length-1,r)),!(e<=n&&n<=r))return t;for(i=void 0===i?O:I(i);r>e;){if(r-e>600){const o=r-e+1,a=n-e+1,u=Math.log(o),c=.5*Math.exp(2*u/3),f=.5*Math.sqrt(u*c*(o-c)/o)*(a-o/2<0?-1:1);rt(t,n,Math.max(e,Math.floor(n-a*c/o+f)),Math.min(r,Math.floor(n+(o-a)*c/o+f)),i)}const o=t[n];let a=e,u=r;for(it(t,e,n),i(t[r],o)>0&&it(t,e,r);a0;)--u}0===i(t[e],o)?it(t,e,u):(++u,it(t,u,r)),u<=n&&(e=u+1),n<=u&&(r=u-1)}return t}function it(t,n,e){const r=t[n];t[n]=t[e],t[e]=r}function ot(t,e=n){let r,i=!1;if(1===e.length){let o;for(const a of t){const t=e(a);(i?n(t,o)>0:0===n(t,t))&&(r=a,o=t,i=!0)}}else for(const n of t)(i?e(n,r)>0:0===e(n,n))&&(r=n,i=!0);return r}function at(t,n,e){if(t=Float64Array.from(function*(t,n){if(void 0===n)for(let n of t)null!=n&&(n=+n)>=n&&(yield n);else{let e=-1;for(let r of t)null!=(r=n(r,++e,t))&&(r=+r)>=r&&(yield r)}}(t,e)),(r=t.length)&&!isNaN(n=+n)){if(n<=0||r<2)return nt(t);if(n>=1)return J(t);var r,i=(r-1)*n,o=Math.floor(i),a=J(rt(t,o).subarray(0,o+1));return a+(nt(t.subarray(o+1))-a)*(i-o)}}function ut(t,n,e=o){if((r=t.length)&&!isNaN(n=+n)){if(n<=0||r<2)return+e(t[0],0,t);if(n>=1)return+e(t[r-1],r-1,t);var r,i=(r-1)*n,a=Math.floor(i),u=+e(t[a],a,t);return u+(+e(t[a+1],a+1,t)-u)*(i-a)}}function ct(t,n,e=o){if(!isNaN(n=+n)){if(r=Float64Array.from(t,((n,r)=>o(e(t[r],r,t)))),n<=0)return et(r);if(n>=1)return tt(r);var r,i=Uint32Array.from(t,((t,n)=>n)),a=r.length-1,u=Math.floor(a*n);return rt(i,u,0,a,((t,n)=>O(r[t],r[n]))),(u=ot(i.subarray(0,u+1),(t=>r[t])))>=0?u:-1}}function ft(t){return Array.from(function*(t){for(const n of t)yield*n}(t))}function st(t,n){return[t,n]}function lt(t,n,e){t=+t,n=+n,e=(i=arguments.length)<2?(n=t,t=0,1):i<3?1:+e;for(var r=-1,i=0|Math.max(0,Math.ceil((n-t)/e)),o=new Array(i);++r+t(n)}function kt(t,n){return n=Math.max(0,t.bandwidth()-2*n)/2,t.round()&&(n=Math.round(n)),e=>+t(e)+n}function Ct(){return!this.__axis}function Pt(t,n){var e=[],r=null,i=null,o=6,a=6,u=3,c="undefined"!=typeof window&&window.devicePixelRatio>1?0:.5,f=t===xt||t===Tt?-1:1,s=t===Tt||t===wt?"x":"y",l=t===xt||t===Mt?St:Et;function h(h){var d=null==r?n.ticks?n.ticks.apply(n,e):n.domain():r,p=null==i?n.tickFormat?n.tickFormat.apply(n,e):mt:i,g=Math.max(o,0)+u,y=n.range(),v=+y[0]+c,_=+y[y.length-1]+c,b=(n.bandwidth?kt:Nt)(n.copy(),c),m=h.selection?h.selection():h,x=m.selectAll(".domain").data([null]),w=m.selectAll(".tick").data(d,n).order(),M=w.exit(),T=w.enter().append("g").attr("class","tick"),A=w.select("line"),S=w.select("text");x=x.merge(x.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),w=w.merge(T),A=A.merge(T.append("line").attr("stroke","currentColor").attr(s+"2",f*o)),S=S.merge(T.append("text").attr("fill","currentColor").attr(s,f*g).attr("dy",t===xt?"0em":t===Mt?"0.71em":"0.32em")),h!==m&&(x=x.transition(h),w=w.transition(h),A=A.transition(h),S=S.transition(h),M=M.transition(h).attr("opacity",At).attr("transform",(function(t){return isFinite(t=b(t))?l(t+c):this.getAttribute("transform")})),T.attr("opacity",At).attr("transform",(function(t){var n=this.parentNode.__axis;return l((n&&isFinite(n=n(t))?n:b(t))+c)}))),M.remove(),x.attr("d",t===Tt||t===wt?a?"M"+f*a+","+v+"H"+c+"V"+_+"H"+f*a:"M"+c+","+v+"V"+_:a?"M"+v+","+f*a+"V"+c+"H"+_+"V"+f*a:"M"+v+","+c+"H"+_),w.attr("opacity",1).attr("transform",(function(t){return l(b(t)+c)})),A.attr(s+"2",f*o),S.attr(s,f*g).text(p),m.filter(Ct).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===wt?"start":t===Tt?"end":"middle"),m.each((function(){this.__axis=b}))}return h.scale=function(t){return arguments.length?(n=t,h):n},h.ticks=function(){return e=Array.from(arguments),h},h.tickArguments=function(t){return arguments.length?(e=null==t?[]:Array.from(t),h):e.slice()},h.tickValues=function(t){return arguments.length?(r=null==t?null:Array.from(t),h):r&&r.slice()},h.tickFormat=function(t){return arguments.length?(i=t,h):i},h.tickSize=function(t){return arguments.length?(o=a=+t,h):o},h.tickSizeInner=function(t){return arguments.length?(o=+t,h):o},h.tickSizeOuter=function(t){return arguments.length?(a=+t,h):a},h.tickPadding=function(t){return arguments.length?(u=+t,h):u},h.offset=function(t){return arguments.length?(c=+t,h):c},h}var zt={value:()=>{}};function $t(){for(var t,n=0,e=arguments.length,r={};n=0&&(n=t.slice(e+1),t=t.slice(0,e)),t&&!r.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))),a=-1,u=o.length;if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++a0)for(var e,r,i=new Array(e),o=0;o=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),Ut.hasOwnProperty(n)?{space:Ut[n],local:t}:t}function Ot(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===qt&&n.documentElement.namespaceURI===qt?n.createElement(t):n.createElementNS(e,t)}}function Bt(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Yt(t){var n=It(t);return(n.local?Bt:Ot)(n)}function Lt(){}function jt(t){return null==t?Lt:function(){return this.querySelector(t)}}function Ht(t){return null==t?[]:Array.isArray(t)?t:Array.from(t)}function Xt(){return[]}function Gt(t){return null==t?Xt:function(){return this.querySelectorAll(t)}}function Vt(t){return function(){return this.matches(t)}}function Wt(t){return function(n){return n.matches(t)}}var Zt=Array.prototype.find;function Kt(){return this.firstElementChild}var Qt=Array.prototype.filter;function Jt(){return Array.from(this.children)}function tn(t){return new Array(t.length)}function nn(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function en(t,n,e,r,i,o){for(var a,u=0,c=n.length,f=o.length;un?1:t>=n?0:NaN}function cn(t){return function(){this.removeAttribute(t)}}function fn(t){return function(){this.removeAttributeNS(t.space,t.local)}}function sn(t,n){return function(){this.setAttribute(t,n)}}function ln(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function hn(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function dn(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function pn(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function gn(t){return function(){this.style.removeProperty(t)}}function yn(t,n,e){return function(){this.style.setProperty(t,n,e)}}function vn(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function _n(t,n){return t.style.getPropertyValue(n)||pn(t).getComputedStyle(t,null).getPropertyValue(n)}function bn(t){return function(){delete this[t]}}function mn(t,n){return function(){this[t]=n}}function xn(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function wn(t){return t.trim().split(/^|\s+/)}function Mn(t){return t.classList||new Tn(t)}function Tn(t){this._node=t,this._names=wn(t.getAttribute("class")||"")}function An(t,n){for(var e=Mn(t),r=-1,i=n.length;++r=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var Gn=[null];function Vn(t,n){this._groups=t,this._parents=n}function Wn(){return new Vn([[document.documentElement]],Gn)}function Zn(t){return"string"==typeof t?new Vn([[document.querySelector(t)]],[document.documentElement]):new Vn([[t]],Gn)}Vn.prototype=Wn.prototype={constructor:Vn,select:function(t){"function"!=typeof t&&(t=jt(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i=m&&(m=b+1);!(_=y[m])&&++m=0;)(r=i[o])&&(a&&4^r.compareDocumentPosition(a)&&a.parentNode.insertBefore(r,a),a=r);return this},sort:function(t){function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}t||(t=un);for(var e=this._groups,r=e.length,i=new Array(r),o=0;o1?this.each((null==n?gn:"function"==typeof n?vn:yn)(t,n,null==e?"":e)):_n(this.node(),t)},property:function(t,n){return arguments.length>1?this.each((null==n?bn:"function"==typeof n?xn:mn)(t,n)):this.node()[t]},classed:function(t,n){var e=wn(t+"");if(arguments.length<2){for(var r=Mn(this.node()),i=-1,o=e.length;++i=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}}))}(t+""),a=o.length;if(!(arguments.length<2)){for(u=n?Ln:Yn,r=0;r()=>t;function fe(t,{sourceEvent:n,subject:e,target:r,identifier:i,active:o,x:a,y:u,dx:c,dy:f,dispatch:s}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:n,enumerable:!0,configurable:!0},subject:{value:e,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:i,enumerable:!0,configurable:!0},active:{value:o,enumerable:!0,configurable:!0},x:{value:a,enumerable:!0,configurable:!0},y:{value:u,enumerable:!0,configurable:!0},dx:{value:c,enumerable:!0,configurable:!0},dy:{value:f,enumerable:!0,configurable:!0},_:{value:s}})}function se(t){return!t.ctrlKey&&!t.button}function le(){return this.parentNode}function he(t,n){return null==n?{x:t.x,y:t.y}:n}function de(){return navigator.maxTouchPoints||"ontouchstart"in this}function pe(t,n,e){t.prototype=n.prototype=e,e.constructor=t}function ge(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[r];return e}function ye(){}fe.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};var ve=.7,_e=1/ve,be="\\s*([+-]?\\d+)\\s*",me="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",xe="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",we=/^#([0-9a-f]{3,8})$/,Me=new RegExp(`^rgb\\(${be},${be},${be}\\)$`),Te=new RegExp(`^rgb\\(${xe},${xe},${xe}\\)$`),Ae=new RegExp(`^rgba\\(${be},${be},${be},${me}\\)$`),Se=new RegExp(`^rgba\\(${xe},${xe},${xe},${me}\\)$`),Ee=new RegExp(`^hsl\\(${me},${xe},${xe}\\)$`),Ne=new RegExp(`^hsla\\(${me},${xe},${xe},${me}\\)$`),ke={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function Ce(){return this.rgb().formatHex()}function Pe(){return this.rgb().formatRgb()}function ze(t){var n,e;return t=(t+"").trim().toLowerCase(),(n=we.exec(t))?(e=n[1].length,n=parseInt(n[1],16),6===e?$e(n):3===e?new qe(n>>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1):8===e?De(n>>24&255,n>>16&255,n>>8&255,(255&n)/255):4===e?De(n>>12&15|n>>8&240,n>>8&15|n>>4&240,n>>4&15|240&n,((15&n)<<4|15&n)/255):null):(n=Me.exec(t))?new qe(n[1],n[2],n[3],1):(n=Te.exec(t))?new qe(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=Ae.exec(t))?De(n[1],n[2],n[3],n[4]):(n=Se.exec(t))?De(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=Ee.exec(t))?Le(n[1],n[2]/100,n[3]/100,1):(n=Ne.exec(t))?Le(n[1],n[2]/100,n[3]/100,n[4]):ke.hasOwnProperty(t)?$e(ke[t]):"transparent"===t?new qe(NaN,NaN,NaN,0):null}function $e(t){return new qe(t>>16&255,t>>8&255,255&t,1)}function De(t,n,e,r){return r<=0&&(t=n=e=NaN),new qe(t,n,e,r)}function Re(t){return t instanceof ye||(t=ze(t)),t?new qe((t=t.rgb()).r,t.g,t.b,t.opacity):new qe}function Fe(t,n,e,r){return 1===arguments.length?Re(t):new qe(t,n,e,null==r?1:r)}function qe(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function Ue(){return`#${Ye(this.r)}${Ye(this.g)}${Ye(this.b)}`}function Ie(){const t=Oe(this.opacity);return`${1===t?"rgb(":"rgba("}${Be(this.r)}, ${Be(this.g)}, ${Be(this.b)}${1===t?")":`, ${t})`}`}function Oe(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function Be(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function Ye(t){return((t=Be(t))<16?"0":"")+t.toString(16)}function Le(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new Xe(t,n,e,r)}function je(t){if(t instanceof Xe)return new Xe(t.h,t.s,t.l,t.opacity);if(t instanceof ye||(t=ze(t)),!t)return new Xe;if(t instanceof Xe)return t;var n=(t=t.rgb()).r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),a=NaN,u=o-i,c=(o+i)/2;return u?(a=n===o?(e-r)/u+6*(e0&&c<1?0:a,new Xe(a,u,c,t.opacity)}function He(t,n,e,r){return 1===arguments.length?je(t):new Xe(t,n,e,null==r?1:r)}function Xe(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function Ge(t){return(t=(t||0)%360)<0?t+360:t}function Ve(t){return Math.max(0,Math.min(1,t||0))}function We(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}pe(ye,ze,{copy(t){return Object.assign(new this.constructor,this,t)},displayable(){return this.rgb().displayable()},hex:Ce,formatHex:Ce,formatHex8:function(){return this.rgb().formatHex8()},formatHsl:function(){return je(this).formatHsl()},formatRgb:Pe,toString:Pe}),pe(qe,Fe,ge(ye,{brighter(t){return t=null==t?_e:Math.pow(_e,t),new qe(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=null==t?ve:Math.pow(ve,t),new qe(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new qe(Be(this.r),Be(this.g),Be(this.b),Oe(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:Ue,formatHex:Ue,formatHex8:function(){return`#${Ye(this.r)}${Ye(this.g)}${Ye(this.b)}${Ye(255*(isNaN(this.opacity)?1:this.opacity))}`},formatRgb:Ie,toString:Ie})),pe(Xe,He,ge(ye,{brighter(t){return t=null==t?_e:Math.pow(_e,t),new Xe(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=null==t?ve:Math.pow(ve,t),new Xe(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+360*(this.h<0),n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new qe(We(t>=240?t-240:t+120,i,r),We(t,i,r),We(t<120?t+240:t-120,i,r),this.opacity)},clamp(){return new Xe(Ge(this.h),Ve(this.s),Ve(this.l),Oe(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=Oe(this.opacity);return`${1===t?"hsl(":"hsla("}${Ge(this.h)}, ${100*Ve(this.s)}%, ${100*Ve(this.l)}%${1===t?")":`, ${t})`}`}}));const Ze=Math.PI/180,Ke=180/Math.PI,Qe=.96422,Je=1,tr=.82521,nr=4/29,er=6/29,rr=3*er*er,ir=er*er*er;function or(t){if(t instanceof ur)return new ur(t.l,t.a,t.b,t.opacity);if(t instanceof pr)return gr(t);t instanceof qe||(t=Re(t));var n,e,r=lr(t.r),i=lr(t.g),o=lr(t.b),a=cr((.2225045*r+.7168786*i+.0606169*o)/Je);return r===i&&i===o?n=e=a:(n=cr((.4360747*r+.3850649*i+.1430804*o)/Qe),e=cr((.0139322*r+.0971045*i+.7141733*o)/tr)),new ur(116*a-16,500*(n-a),200*(a-e),t.opacity)}function ar(t,n,e,r){return 1===arguments.length?or(t):new ur(t,n,e,null==r?1:r)}function ur(t,n,e,r){this.l=+t,this.a=+n,this.b=+e,this.opacity=+r}function cr(t){return t>ir?Math.pow(t,1/3):t/rr+nr}function fr(t){return t>er?t*t*t:rr*(t-nr)}function sr(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function lr(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function hr(t){if(t instanceof pr)return new pr(t.h,t.c,t.l,t.opacity);if(t instanceof ur||(t=or(t)),0===t.a&&0===t.b)return new pr(NaN,0=1?(e=1,n-1):Math.floor(e*n),i=t[r],o=t[r+1],a=r>0?t[r-1]:2*i-o,u=r()=>t;function Cr(t,n){return function(e){return t+e*n}}function Pr(t,n){var e=n-t;return e?Cr(t,e>180||e<-180?e-360*Math.round(e/360):e):kr(isNaN(t)?n:t)}function zr(t){return 1==(t=+t)?$r:function(n,e){return e-n?function(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}(n,e,t):kr(isNaN(n)?e:n)}}function $r(t,n){var e=n-t;return e?Cr(t,e):kr(isNaN(t)?n:t)}var Dr=function t(n){var e=zr(n);function r(t,n){var r=e((t=Fe(t)).r,(n=Fe(n)).r),i=e(t.g,n.g),o=e(t.b,n.b),a=$r(t.opacity,n.opacity);return function(n){return t.r=r(n),t.g=i(n),t.b=o(n),t.opacity=a(n),t+""}}return r.gamma=t,r}(1);function Rr(t){return function(n){var e,r,i=n.length,o=new Array(i),a=new Array(i),u=new Array(i);for(e=0;eo&&(i=n.slice(o,i),u[a]?u[a]+=i:u[++a]=i),(e=e[0])===(r=r[0])?u[a]?u[a]+=r:u[++a]=r:(u[++a]=null,c.push({i:a,x:Yr(e,r)})),o=Hr.lastIndex;return o180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+"rotate(",null,r)-2,x:Yr(t,n)})):n&&e.push(i(e)+"rotate("+n+r)}(o.rotate,a.rotate,u,c),function(t,n,e,o){t!==n?o.push({i:e.push(i(e)+"skewX(",null,r)-2,x:Yr(t,n)}):n&&e.push(i(e)+"skewX("+n+r)}(o.skewX,a.skewX,u,c),function(t,n,e,r,o,a){if(t!==e||n!==r){var u=o.push(i(o)+"scale(",null,",",null,")");a.push({i:u-4,x:Yr(t,e)},{i:u-2,x:Yr(n,r)})}else 1===e&&1===r||o.push(i(o)+"scale("+e+","+r+")")}(o.scaleX,o.scaleY,a.scaleX,a.scaleY,u,c),o=a=null,function(t){for(var n,e=-1,r=c.length;++e=0&&n._call.call(void 0,t),n=n._next;--yi}function Ci(){xi=(mi=Mi.now())+wi,yi=vi=0;try{ki()}finally{yi=0,function(){var t,n,e=pi,r=1/0;for(;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:pi=n);gi=t,zi(r)}(),xi=0}}function Pi(){var t=Mi.now(),n=t-mi;n>bi&&(wi-=n,mi=t)}function zi(t){yi||(vi&&(vi=clearTimeout(vi)),t-xi>24?(t<1/0&&(vi=setTimeout(Ci,t-Mi.now()-wi)),_i&&(_i=clearInterval(_i))):(_i||(mi=Mi.now(),_i=setInterval(Pi,bi)),yi=1,Ti(Ci)))}function $i(t,n,e){var r=new Ei;return n=null==n?0:+n,r.restart((e=>{r.stop(),t(e+n)}),n,e),r}Ei.prototype=Ni.prototype={constructor:Ei,restart:function(t,n,e){if("function"!=typeof t)throw new TypeError("callback is not a function");e=(null==e?Ai():+e)+(null==n?0:+n),this._next||gi===this||(gi?gi._next=this:pi=this,gi=this),this._call=t,this._time=e,zi()},stop:function(){this._call&&(this._call=null,this._time=1/0,zi())}};var Di=$t("start","end","cancel","interrupt"),Ri=[],Fi=0,qi=1,Ui=2,Ii=3,Oi=4,Bi=5,Yi=6;function Li(t,n,e,r,i,o){var a=t.__transition;if(a){if(e in a)return}else t.__transition={};!function(t,n,e){var r,i=t.__transition;function o(t){e.state=qi,e.timer.restart(a,e.delay,e.time),e.delay<=t&&a(t-e.delay)}function a(o){var f,s,l,h;if(e.state!==qi)return c();for(f in i)if((h=i[f]).name===e.name){if(h.state===Ii)return $i(a);h.state===Oi?(h.state=Yi,h.timer.stop(),h.on.call("interrupt",t,t.__data__,h.index,h.group),delete i[f]):+fFi)throw new Error("too late; already scheduled");return e}function Hi(t,n){var e=Xi(t,n);if(e.state>Ii)throw new Error("too late; already running");return e}function Xi(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("transition not found");return e}function Gi(t,n){var e,r,i,o=t.__transition,a=!0;if(o){for(i in n=null==n?null:n+"",o)(e=o[i]).name===n?(r=e.state>Ui&&e.state=0&&(t=t.slice(0,n)),!t||"start"===t}))}(n)?ji:Hi;return function(){var a=o(this,t),u=a.on;u!==r&&(i=(r=u).copy()).on(n,e),a.on=i}}(e,t,n))},attr:function(t,n){var e=It(t),r="transform"===e?ni:Ki;return this.attrTween(t,"function"==typeof n?(e.local?ro:eo)(e,r,Zi(this,"attr."+t,n)):null==n?(e.local?Ji:Qi)(e):(e.local?no:to)(e,r,n))},attrTween:function(t,n){var e="attr."+t;if(arguments.length<2)return(e=this.tween(e))&&e._value;if(null==n)return this.tween(e,null);if("function"!=typeof n)throw new Error;var r=It(t);return this.tween(e,(r.local?io:oo)(r,n))},style:function(t,n,e){var r="transform"==(t+="")?ti:Ki;return null==n?this.styleTween(t,function(t,n){var e,r,i;return function(){var o=_n(this,t),a=(this.style.removeProperty(t),_n(this,t));return o===a?null:o===e&&a===r?i:i=n(e=o,r=a)}}(t,r)).on("end.style."+t,lo(t)):"function"==typeof n?this.styleTween(t,function(t,n,e){var r,i,o;return function(){var a=_n(this,t),u=e(this),c=u+"";return null==u&&(this.style.removeProperty(t),c=u=_n(this,t)),a===c?null:a===r&&c===i?o:(i=c,o=n(r=a,u))}}(t,r,Zi(this,"style."+t,n))).each(function(t,n){var e,r,i,o,a="style."+n,u="end."+a;return function(){var c=Hi(this,t),f=c.on,s=null==c.value[a]?o||(o=lo(n)):void 0;f===e&&i===s||(r=(e=f).copy()).on(u,i=s),c.on=r}}(this._id,t)):this.styleTween(t,function(t,n,e){var r,i,o=e+"";return function(){var a=_n(this,t);return a===o?null:a===r?i:i=n(r=a,e)}}(t,r,n),e).on("end.style."+t,null)},styleTween:function(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,function(t,n,e){var r,i;function o(){var o=n.apply(this,arguments);return o!==i&&(r=(i=o)&&function(t,n,e){return function(r){this.style.setProperty(t,n.call(this,r),e)}}(t,o,e)),r}return o._value=n,o}(t,n,null==e?"":e))},text:function(t){return this.tween("text","function"==typeof t?function(t){return function(){var n=t(this);this.textContent=null==n?"":n}}(Zi(this,"text",t)):function(t){return function(){this.textContent=t}}(null==t?"":t+""))},textTween:function(t){var n="text";if(arguments.length<1)return(n=this.tween(n))&&n._value;if(null==t)return this.tween(n,null);if("function"!=typeof t)throw new Error;return this.tween(n,function(t){var n,e;function r(){var r=t.apply(this,arguments);return r!==e&&(n=(e=r)&&function(t){return function(n){this.textContent=t.call(this,n)}}(r)),n}return r._value=t,r}(t))},remove:function(){return this.on("end.remove",function(t){return function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}}(this._id))},tween:function(t,n){var e=this._id;if(t+="",arguments.length<2){for(var r,i=Xi(this.node(),e).tween,o=0,a=i.length;o()=>t;function Qo(t,{sourceEvent:n,target:e,selection:r,mode:i,dispatch:o}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:n,enumerable:!0,configurable:!0},target:{value:e,enumerable:!0,configurable:!0},selection:{value:r,enumerable:!0,configurable:!0},mode:{value:i,enumerable:!0,configurable:!0},_:{value:o}})}function Jo(t){t.preventDefault(),t.stopImmediatePropagation()}var ta={name:"drag"},na={name:"space"},ea={name:"handle"},ra={name:"center"};const{abs:ia,max:oa,min:aa}=Math;function ua(t){return[+t[0],+t[1]]}function ca(t){return[ua(t[0]),ua(t[1])]}var fa={name:"x",handles:["w","e"].map(va),input:function(t,n){return null==t?null:[[+t[0],n[0][1]],[+t[1],n[1][1]]]},output:function(t){return t&&[t[0][0],t[1][0]]}},sa={name:"y",handles:["n","s"].map(va),input:function(t,n){return null==t?null:[[n[0][0],+t[0]],[n[1][0],+t[1]]]},output:function(t){return t&&[t[0][1],t[1][1]]}},la={name:"xy",handles:["n","w","e","s","nw","ne","sw","se"].map(va),input:function(t){return null==t?null:ca(t)},output:function(t){return t}},ha={overlay:"crosshair",selection:"move",n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},da={e:"w",w:"e",nw:"ne",ne:"nw",se:"sw",sw:"se"},pa={n:"s",s:"n",nw:"sw",ne:"se",se:"ne",sw:"nw"},ga={overlay:1,selection:1,n:null,e:1,s:null,w:-1,nw:-1,ne:1,se:1,sw:-1},ya={overlay:1,selection:1,n:-1,e:null,s:1,w:null,nw:-1,ne:-1,se:1,sw:1};function va(t){return{type:t}}function _a(t){return!t.ctrlKey&&!t.button}function ba(){var t=this.ownerSVGElement||this;return t.hasAttribute("viewBox")?[[(t=t.viewBox.baseVal).x,t.y],[t.x+t.width,t.y+t.height]]:[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]}function ma(){return navigator.maxTouchPoints||"ontouchstart"in this}function xa(t){for(;!t.__brush;)if(!(t=t.parentNode))return;return t.__brush}function wa(t){var n,e=ba,r=_a,i=ma,o=!0,a=$t("start","brush","end"),u=6;function c(n){var e=n.property("__brush",g).selectAll(".overlay").data([va("overlay")]);e.enter().append("rect").attr("class","overlay").attr("pointer-events","all").attr("cursor",ha.overlay).merge(e).each((function(){var t=xa(this).extent;Zn(this).attr("x",t[0][0]).attr("y",t[0][1]).attr("width",t[1][0]-t[0][0]).attr("height",t[1][1]-t[0][1])})),n.selectAll(".selection").data([va("selection")]).enter().append("rect").attr("class","selection").attr("cursor",ha.selection).attr("fill","#777").attr("fill-opacity",.3).attr("stroke","#fff").attr("shape-rendering","crispEdges");var r=n.selectAll(".handle").data(t.handles,(function(t){return t.type}));r.exit().remove(),r.enter().append("rect").attr("class",(function(t){return"handle handle--"+t.type})).attr("cursor",(function(t){return ha[t.type]})),n.each(f).attr("fill","none").attr("pointer-events","all").on("mousedown.brush",h).filter(i).on("touchstart.brush",h).on("touchmove.brush",d).on("touchend.brush touchcancel.brush",p).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function f(){var t=Zn(this),n=xa(this).selection;n?(t.selectAll(".selection").style("display",null).attr("x",n[0][0]).attr("y",n[0][1]).attr("width",n[1][0]-n[0][0]).attr("height",n[1][1]-n[0][1]),t.selectAll(".handle").style("display",null).attr("x",(function(t){return"e"===t.type[t.type.length-1]?n[1][0]-u/2:n[0][0]-u/2})).attr("y",(function(t){return"s"===t.type[0]?n[1][1]-u/2:n[0][1]-u/2})).attr("width",(function(t){return"n"===t.type||"s"===t.type?n[1][0]-n[0][0]+u:u})).attr("height",(function(t){return"e"===t.type||"w"===t.type?n[1][1]-n[0][1]+u:u}))):t.selectAll(".selection,.handle").style("display","none").attr("x",null).attr("y",null).attr("width",null).attr("height",null)}function s(t,n,e){var r=t.__brush.emitter;return!r||e&&r.clean?new l(t,n,e):r}function l(t,n,e){this.that=t,this.args=n,this.state=t.__brush,this.active=0,this.clean=e}function h(e){if((!n||e.touches)&&r.apply(this,arguments)){var i,a,u,c,l,h,d,p,g,y,v,_=this,b=e.target.__data__.type,m="selection"===(o&&e.metaKey?b="overlay":b)?ta:o&&e.altKey?ra:ea,x=t===sa?null:ga[b],w=t===fa?null:ya[b],M=xa(_),T=M.extent,A=M.selection,S=T[0][0],E=T[0][1],N=T[1][0],k=T[1][1],C=0,P=0,z=x&&w&&o&&e.shiftKey,$=Array.from(e.touches||[e],(t=>{const n=t.identifier;return(t=ne(t,_)).point0=t.slice(),t.identifier=n,t}));Gi(_);var D=s(_,arguments,!0).beforestart();if("overlay"===b){A&&(g=!0);const n=[$[0],$[1]||$[0]];M.selection=A=[[i=t===sa?S:aa(n[0][0],n[1][0]),u=t===fa?E:aa(n[0][1],n[1][1])],[l=t===sa?N:oa(n[0][0],n[1][0]),d=t===fa?k:oa(n[0][1],n[1][1])]],$.length>1&&I(e)}else i=A[0][0],u=A[0][1],l=A[1][0],d=A[1][1];a=i,c=u,h=l,p=d;var R=Zn(_).attr("pointer-events","none"),F=R.selectAll(".overlay").attr("cursor",ha[b]);if(e.touches)D.moved=U,D.ended=O;else{var q=Zn(e.view).on("mousemove.brush",U,!0).on("mouseup.brush",O,!0);o&&q.on("keydown.brush",(function(t){switch(t.keyCode){case 16:z=x&&w;break;case 18:m===ea&&(x&&(l=h-C*x,i=a+C*x),w&&(d=p-P*w,u=c+P*w),m=ra,I(t));break;case 32:m!==ea&&m!==ra||(x<0?l=h-C:x>0&&(i=a-C),w<0?d=p-P:w>0&&(u=c-P),m=na,F.attr("cursor",ha.selection),I(t));break;default:return}Jo(t)}),!0).on("keyup.brush",(function(t){switch(t.keyCode){case 16:z&&(y=v=z=!1,I(t));break;case 18:m===ra&&(x<0?l=h:x>0&&(i=a),w<0?d=p:w>0&&(u=c),m=ea,I(t));break;case 32:m===na&&(t.altKey?(x&&(l=h-C*x,i=a+C*x),w&&(d=p-P*w,u=c+P*w),m=ra):(x<0?l=h:x>0&&(i=a),w<0?d=p:w>0&&(u=c),m=ea),F.attr("cursor",ha[b]),I(t));break;default:return}Jo(t)}),!0),ae(e.view)}f.call(_),D.start(e,m.name)}function U(t){for(const n of t.changedTouches||[t])for(const t of $)t.identifier===n.identifier&&(t.cur=ne(n,_));if(z&&!y&&!v&&1===$.length){const t=$[0];ia(t.cur[0]-t[0])>ia(t.cur[1]-t[1])?v=!0:y=!0}for(const t of $)t.cur&&(t[0]=t.cur[0],t[1]=t.cur[1]);g=!0,Jo(t),I(t)}function I(t){const n=$[0],e=n.point0;var r;switch(C=n[0]-e[0],P=n[1]-e[1],m){case na:case ta:x&&(C=oa(S-i,aa(N-l,C)),a=i+C,h=l+C),w&&(P=oa(E-u,aa(k-d,P)),c=u+P,p=d+P);break;case ea:$[1]?(x&&(a=oa(S,aa(N,$[0][0])),h=oa(S,aa(N,$[1][0])),x=1),w&&(c=oa(E,aa(k,$[0][1])),p=oa(E,aa(k,$[1][1])),w=1)):(x<0?(C=oa(S-i,aa(N-i,C)),a=i+C,h=l):x>0&&(C=oa(S-l,aa(N-l,C)),a=i,h=l+C),w<0?(P=oa(E-u,aa(k-u,P)),c=u+P,p=d):w>0&&(P=oa(E-d,aa(k-d,P)),c=u,p=d+P));break;case ra:x&&(a=oa(S,aa(N,i-C*x)),h=oa(S,aa(N,l+C*x))),w&&(c=oa(E,aa(k,u-P*w)),p=oa(E,aa(k,d+P*w)))}ht+e))}function za(t,n){var e=0,r=null,i=null,o=null;function a(a){var u,c=a.length,f=new Array(c),s=Pa(0,c),l=new Array(c*c),h=new Array(c),d=0;a=Float64Array.from({length:c*c},n?(t,n)=>a[n%c][n/c|0]:(t,n)=>a[n/c|0][n%c]);for(let n=0;nr(f[t],f[n])));for(const e of s){const r=n;if(t){const t=Pa(1+~c,c).filter((t=>t<0?a[~t*c+e]:a[e*c+t]));i&&t.sort(((t,n)=>i(t<0?-a[~t*c+e]:a[e*c+t],n<0?-a[~n*c+e]:a[e*c+n])));for(const r of t)if(r<0){(l[~r*c+e]||(l[~r*c+e]={source:null,target:null})).target={index:e,startAngle:n,endAngle:n+=a[~r*c+e]*d,value:a[~r*c+e]}}else{(l[e*c+r]||(l[e*c+r]={source:null,target:null})).source={index:e,startAngle:n,endAngle:n+=a[e*c+r]*d,value:a[e*c+r]}}h[e]={index:e,startAngle:r,endAngle:n,value:f[e]}}else{const t=Pa(0,c).filter((t=>a[e*c+t]||a[t*c+e]));i&&t.sort(((t,n)=>i(a[e*c+t],a[e*c+n])));for(const r of t){let t;if(e=0))throw new Error(`invalid digits: ${t}`);if(n>15)return qa;const e=10**n;return function(t){this._+=t[0];for(let n=1,r=t.length;nRa)if(Math.abs(s*u-c*f)>Ra&&i){let h=e-o,d=r-a,p=u*u+c*c,g=h*h+d*d,y=Math.sqrt(p),v=Math.sqrt(l),_=i*Math.tan(($a-Math.acos((p+l-g)/(2*y*v)))/2),b=_/v,m=_/y;Math.abs(b-1)>Ra&&this._append`L${t+b*f},${n+b*s}`,this._append`A${i},${i},0,0,${+(s*h>f*d)},${this._x1=t+m*u},${this._y1=n+m*c}`}else this._append`L${this._x1=t},${this._y1=n}`;else;}arc(t,n,e,r,i,o){if(t=+t,n=+n,o=!!o,(e=+e)<0)throw new Error(`negative radius: ${e}`);let a=e*Math.cos(r),u=e*Math.sin(r),c=t+a,f=n+u,s=1^o,l=o?r-i:i-r;null===this._x1?this._append`M${c},${f}`:(Math.abs(this._x1-c)>Ra||Math.abs(this._y1-f)>Ra)&&this._append`L${c},${f}`,e&&(l<0&&(l=l%Da+Da),l>Fa?this._append`A${e},${e},0,1,${s},${t-a},${n-u}A${e},${e},0,1,${s},${this._x1=c},${this._y1=f}`:l>Ra&&this._append`A${e},${e},0,${+(l>=$a)},${s},${this._x1=t+e*Math.cos(i)},${this._y1=n+e*Math.sin(i)}`)}rect(t,n,e,r){this._append`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}h${e=+e}v${+r}h${-e}Z`}toString(){return this._}};function Ia(){return new Ua}Ia.prototype=Ua.prototype;var Oa=Array.prototype.slice;function Ba(t){return function(){return t}}function Ya(t){return t.source}function La(t){return t.target}function ja(t){return t.radius}function Ha(t){return t.startAngle}function Xa(t){return t.endAngle}function Ga(){return 0}function Va(){return 10}function Wa(t){var n=Ya,e=La,r=ja,i=ja,o=Ha,a=Xa,u=Ga,c=null;function f(){var f,s=n.apply(this,arguments),l=e.apply(this,arguments),h=u.apply(this,arguments)/2,d=Oa.call(arguments),p=+r.apply(this,(d[0]=s,d)),g=o.apply(this,d)-Ea,y=a.apply(this,d)-Ea,v=+i.apply(this,(d[0]=l,d)),_=o.apply(this,d)-Ea,b=a.apply(this,d)-Ea;if(c||(c=f=Ia()),h>Ca&&(Ma(y-g)>2*h+Ca?y>g?(g+=h,y-=h):(g-=h,y+=h):g=y=(g+y)/2,Ma(b-_)>2*h+Ca?b>_?(_+=h,b-=h):(_-=h,b+=h):_=b=(_+b)/2),c.moveTo(p*Ta(g),p*Aa(g)),c.arc(0,0,p,g,y),g!==_||y!==b)if(t){var m=v-+t.apply(this,arguments),x=(_+b)/2;c.quadraticCurveTo(0,0,m*Ta(_),m*Aa(_)),c.lineTo(v*Ta(x),v*Aa(x)),c.lineTo(m*Ta(b),m*Aa(b))}else c.quadraticCurveTo(0,0,v*Ta(_),v*Aa(_)),c.arc(0,0,v,_,b);if(c.quadraticCurveTo(0,0,p*Ta(g),p*Aa(g)),c.closePath(),f)return c=null,f+""||null}return t&&(f.headRadius=function(n){return arguments.length?(t="function"==typeof n?n:Ba(+n),f):t}),f.radius=function(t){return arguments.length?(r=i="function"==typeof t?t:Ba(+t),f):r},f.sourceRadius=function(t){return arguments.length?(r="function"==typeof t?t:Ba(+t),f):r},f.targetRadius=function(t){return arguments.length?(i="function"==typeof t?t:Ba(+t),f):i},f.startAngle=function(t){return arguments.length?(o="function"==typeof t?t:Ba(+t),f):o},f.endAngle=function(t){return arguments.length?(a="function"==typeof t?t:Ba(+t),f):a},f.padAngle=function(t){return arguments.length?(u="function"==typeof t?t:Ba(+t),f):u},f.source=function(t){return arguments.length?(n=t,f):n},f.target=function(t){return arguments.length?(e=t,f):e},f.context=function(t){return arguments.length?(c=null==t?null:t,f):c},f}var Za=Array.prototype.slice;function Ka(t,n){return t-n}var Qa=t=>()=>t;function Ja(t,n){for(var e,r=-1,i=n.length;++rr!=d>r&&e<(h-f)*(r-s)/(d-s)+f&&(i=-i)}return i}function nu(t,n,e){var r,i,o,a;return function(t,n,e){return(n[0]-t[0])*(e[1]-t[1])==(e[0]-t[0])*(n[1]-t[1])}(t,n,e)&&(i=t[r=+(t[0]===n[0])],o=e[r],a=n[r],i<=o&&o<=a||a<=o&&o<=i)}function eu(){}var ru=[[],[[[1,1.5],[.5,1]]],[[[1.5,1],[1,1.5]]],[[[1.5,1],[.5,1]]],[[[1,.5],[1.5,1]]],[[[1,1.5],[.5,1]],[[1,.5],[1.5,1]]],[[[1,.5],[1,1.5]]],[[[1,.5],[.5,1]]],[[[.5,1],[1,.5]]],[[[1,1.5],[1,.5]]],[[[.5,1],[1,.5]],[[1.5,1],[1,1.5]]],[[[1.5,1],[1,.5]]],[[[.5,1],[1.5,1]]],[[[1,1.5],[1.5,1]]],[[[.5,1],[1,1.5]]],[]];function iu(){var t=1,n=1,e=K,r=u;function i(t){var n=e(t);if(Array.isArray(n))n=n.slice().sort(Ka);else{const e=M(t,ou);for(n=G(...Z(e[0],e[1],n),n);n[n.length-1]>=e[1];)n.pop();for(;n[1]o(t,n)))}function o(e,i){const o=null==i?NaN:+i;if(isNaN(o))throw new Error(`invalid value: ${i}`);var u=[],c=[];return function(e,r,i){var o,u,c,f,s,l,h=new Array,d=new Array;o=u=-1,f=au(e[0],r),ru[f<<1].forEach(p);for(;++o=r,ru[s<<2].forEach(p);for(;++o0?u.push([t]):c.push(t)})),c.forEach((function(t){for(var n,e=0,r=u.length;e0&&o0&&a=0&&o>=0))throw new Error("invalid size");return t=r,n=o,i},i.thresholds=function(t){return arguments.length?(e="function"==typeof t?t:Array.isArray(t)?Qa(Za.call(t)):Qa(t),i):e},i.smooth=function(t){return arguments.length?(r=t?u:eu,i):r===u},i}function ou(t){return isFinite(t)?t:NaN}function au(t,n){return null!=t&&+t>=n}function uu(t){return null==t||isNaN(t=+t)?-1/0:t}function cu(t,n,e,r){const i=r-n,o=e-n,a=isFinite(i)||isFinite(o)?i/o:Math.sign(i)/Math.sign(o);return isNaN(a)?t:t+a-.5}function fu(t){return t[0]}function su(t){return t[1]}function lu(){return 1}const hu=134217729,du=33306690738754706e-32;function pu(t,n,e,r,i){let o,a,u,c,f=n[0],s=r[0],l=0,h=0;s>f==s>-f?(o=f,f=n[++l]):(o=s,s=r[++h]);let d=0;if(lf==s>-f?(a=f+o,u=o-(a-f),f=n[++l]):(a=s+o,u=o-(a-s),s=r[++h]),o=a,0!==u&&(i[d++]=u);lf==s>-f?(a=o+f,c=a-o,u=o-(a-c)+(f-c),f=n[++l]):(a=o+s,c=a-o,u=o-(a-c)+(s-c),s=r[++h]),o=a,0!==u&&(i[d++]=u);for(;l=33306690738754716e-32*f?c:-function(t,n,e,r,i,o,a){let u,c,f,s,l,h,d,p,g,y,v,_,b,m,x,w,M,T;const A=t-i,S=e-i,E=n-o,N=r-o;m=A*N,h=hu*A,d=h-(h-A),p=A-d,h=hu*N,g=h-(h-N),y=N-g,x=p*y-(m-d*g-p*g-d*y),w=E*S,h=hu*E,d=h-(h-E),p=E-d,h=hu*S,g=h-(h-S),y=S-g,M=p*y-(w-d*g-p*g-d*y),v=x-M,l=x-v,_u[0]=x-(v+l)+(l-M),_=m+v,l=_-m,b=m-(_-l)+(v-l),v=b-w,l=b-v,_u[1]=b-(v+l)+(l-w),T=_+v,l=T-_,_u[2]=_-(T-l)+(v-l),_u[3]=T;let k=function(t,n){let e=n[0];for(let r=1;r=C||-k>=C)return k;if(l=t-A,u=t-(A+l)+(l-i),l=e-S,f=e-(S+l)+(l-i),l=n-E,c=n-(E+l)+(l-o),l=r-N,s=r-(N+l)+(l-o),0===u&&0===c&&0===f&&0===s)return k;if(C=vu*a+du*Math.abs(k),k+=A*s+N*u-(E*f+S*c),k>=C||-k>=C)return k;m=u*N,h=hu*u,d=h-(h-u),p=u-d,h=hu*N,g=h-(h-N),y=N-g,x=p*y-(m-d*g-p*g-d*y),w=c*S,h=hu*c,d=h-(h-c),p=c-d,h=hu*S,g=h-(h-S),y=S-g,M=p*y-(w-d*g-p*g-d*y),v=x-M,l=x-v,wu[0]=x-(v+l)+(l-M),_=m+v,l=_-m,b=m-(_-l)+(v-l),v=b-w,l=b-v,wu[1]=b-(v+l)+(l-w),T=_+v,l=T-_,wu[2]=_-(T-l)+(v-l),wu[3]=T;const P=pu(4,_u,4,wu,bu);m=A*s,h=hu*A,d=h-(h-A),p=A-d,h=hu*s,g=h-(h-s),y=s-g,x=p*y-(m-d*g-p*g-d*y),w=E*f,h=hu*E,d=h-(h-E),p=E-d,h=hu*f,g=h-(h-f),y=f-g,M=p*y-(w-d*g-p*g-d*y),v=x-M,l=x-v,wu[0]=x-(v+l)+(l-M),_=m+v,l=_-m,b=m-(_-l)+(v-l),v=b-w,l=b-v,wu[1]=b-(v+l)+(l-w),T=_+v,l=T-_,wu[2]=_-(T-l)+(v-l),wu[3]=T;const z=pu(P,bu,4,wu,mu);m=u*s,h=hu*u,d=h-(h-u),p=u-d,h=hu*s,g=h-(h-s),y=s-g,x=p*y-(m-d*g-p*g-d*y),w=c*f,h=hu*c,d=h-(h-c),p=c-d,h=hu*f,g=h-(h-f),y=f-g,M=p*y-(w-d*g-p*g-d*y),v=x-M,l=x-v,wu[0]=x-(v+l)+(l-M),_=m+v,l=_-m,b=m-(_-l)+(v-l),v=b-w,l=b-v,wu[1]=b-(v+l)+(l-w),T=_+v,l=T-_,wu[2]=_-(T-l)+(v-l),wu[3]=T;const $=pu(z,mu,4,wu,xu);return xu[$-1]}(t,n,e,r,i,o,f)}const Tu=Math.pow(2,-52),Au=new Uint32Array(512);class Su{static from(t,n=zu,e=$u){const r=t.length,i=new Float64Array(2*r);for(let o=0;o>1;if(n>0&&"number"!=typeof t[0])throw new Error("Expected coords to contain numbers.");this.coords=t;const e=Math.max(2*n-5,0);this._triangles=new Uint32Array(3*e),this._halfedges=new Int32Array(3*e),this._hashSize=Math.ceil(Math.sqrt(n)),this._hullPrev=new Uint32Array(n),this._hullNext=new Uint32Array(n),this._hullTri=new Uint32Array(n),this._hullHash=new Int32Array(this._hashSize),this._ids=new Uint32Array(n),this._dists=new Float64Array(n),this.update()}update(){const{coords:t,_hullPrev:n,_hullNext:e,_hullTri:r,_hullHash:i}=this,o=t.length>>1;let a=1/0,u=1/0,c=-1/0,f=-1/0;for(let n=0;nc&&(c=e),r>f&&(f=r),this._ids[n]=n}const s=(a+c)/2,l=(u+f)/2;let h,d,p;for(let n=0,e=1/0;n0&&(d=n,e=r)}let v=t[2*d],_=t[2*d+1],b=1/0;for(let n=0;nr&&(n[e++]=i,r=o)}return this.hull=n.subarray(0,e),this.triangles=new Uint32Array(0),void(this.halfedges=new Uint32Array(0))}if(Mu(g,y,v,_,m,x)<0){const t=d,n=v,e=_;d=p,v=m,_=x,p=t,m=n,x=e}const w=function(t,n,e,r,i,o){const a=e-t,u=r-n,c=i-t,f=o-n,s=a*a+u*u,l=c*c+f*f,h=.5/(a*f-u*c),d=t+(f*s-u*l)*h,p=n+(a*l-c*s)*h;return{x:d,y:p}}(g,y,v,_,m,x);this._cx=w.x,this._cy=w.y;for(let n=0;n0&&Math.abs(f-o)<=Tu&&Math.abs(s-a)<=Tu)continue;if(o=f,a=s,c===h||c===d||c===p)continue;let l=0;for(let t=0,n=this._hashKey(f,s);t=0;)if(y=g,y===l){y=-1;break}if(-1===y)continue;let v=this._addTriangle(y,c,e[y],-1,-1,r[y]);r[c]=this._legalize(v+2),r[y]=v,M++;let _=e[y];for(;g=e[_],Mu(f,s,t[2*_],t[2*_+1],t[2*g],t[2*g+1])<0;)v=this._addTriangle(_,c,g,r[c],-1,r[_]),r[c]=this._legalize(v+2),e[_]=_,M--,_=g;if(y===l)for(;g=n[y],Mu(f,s,t[2*g],t[2*g+1],t[2*y],t[2*y+1])<0;)v=this._addTriangle(g,c,y,-1,r[y],r[g]),this._legalize(v+2),r[g]=v,e[y]=y,M--,y=g;this._hullStart=n[c]=y,e[y]=n[_]=c,e[c]=_,i[this._hashKey(f,s)]=c,i[this._hashKey(t[2*y],t[2*y+1])]=y}this.hull=new Uint32Array(M);for(let t=0,n=this._hullStart;t0?3-e:1+e)/4}(t-this._cx,n-this._cy)*this._hashSize)%this._hashSize}_legalize(t){const{_triangles:n,_halfedges:e,coords:r}=this;let i=0,o=0;for(;;){const a=e[t],u=t-t%3;if(o=u+(t+2)%3,-1===a){if(0===i)break;t=Au[--i];continue}const c=a-a%3,f=u+(t+1)%3,s=c+(a+2)%3,l=n[o],h=n[t],d=n[f],p=n[s];if(Nu(r[2*l],r[2*l+1],r[2*h],r[2*h+1],r[2*d],r[2*d+1],r[2*p],r[2*p+1])){n[t]=p,n[a]=l;const r=e[s];if(-1===r){let n=this._hullStart;do{if(this._hullTri[n]===s){this._hullTri[n]=t;break}n=this._hullPrev[n]}while(n!==this._hullStart)}this._link(t,r),this._link(a,e[o]),this._link(o,s);const u=c+(a+1)%3;i=e&&n[t[a]]>o;)t[a+1]=t[a--];t[a+1]=r}else{let i=e+1,o=r;Pu(t,e+r>>1,i),n[t[e]]>n[t[r]]&&Pu(t,e,r),n[t[i]]>n[t[r]]&&Pu(t,i,r),n[t[e]]>n[t[i]]&&Pu(t,e,i);const a=t[i],u=n[a];for(;;){do{i++}while(n[t[i]]u);if(o=o-e?(Cu(t,n,i,r),Cu(t,n,e,o-1)):(Cu(t,n,e,o-1),Cu(t,n,i,r))}}function Pu(t,n,e){const r=t[n];t[n]=t[e],t[e]=r}function zu(t){return t[0]}function $u(t){return t[1]}const Du=1e-6;class Ru{constructor(){this._x0=this._y0=this._x1=this._y1=null,this._=""}moveTo(t,n){this._+=`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}`}closePath(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")}lineTo(t,n){this._+=`L${this._x1=+t},${this._y1=+n}`}arc(t,n,e){const r=(t=+t)+(e=+e),i=n=+n;if(e<0)throw new Error("negative radius");null===this._x1?this._+=`M${r},${i}`:(Math.abs(this._x1-r)>Du||Math.abs(this._y1-i)>Du)&&(this._+="L"+r+","+i),e&&(this._+=`A${e},${e},0,1,1,${t-e},${n}A${e},${e},0,1,1,${this._x1=r},${this._y1=i}`)}rect(t,n,e,r){this._+=`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}h${+e}v${+r}h${-e}Z`}value(){return this._||null}}class Fu{constructor(){this._=[]}moveTo(t,n){this._.push([t,n])}closePath(){this._.push(this._[0].slice())}lineTo(t,n){this._.push([t,n])}value(){return this._.length?this._:null}}class qu{constructor(t,[n,e,r,i]=[0,0,960,500]){if(!((r=+r)>=(n=+n)&&(i=+i)>=(e=+e)))throw new Error("invalid bounds");this.delaunay=t,this._circumcenters=new Float64Array(2*t.points.length),this.vectors=new Float64Array(2*t.points.length),this.xmax=r,this.xmin=n,this.ymax=i,this.ymin=e,this._init()}update(){return this.delaunay.update(),this._init(),this}_init(){const{delaunay:{points:t,hull:n,triangles:e},vectors:r}=this;let i,o;const a=this.circumcenters=this._circumcenters.subarray(0,e.length/3*2);for(let r,u,c=0,f=0,s=e.length;c1;)i-=2;for(let t=2;t0){if(n>=this.ymax)return null;(i=(this.ymax-n)/r)0){if(t>=this.xmax)return null;(i=(this.xmax-t)/e)this.xmax?2:0)|(nthis.ymax?8:0)}_simplify(t){if(t&&t.length>4){for(let n=0;n2&&function(t){const{triangles:n,coords:e}=t;for(let t=0;t1e-10)return!1}return!0}(t)){this.collinear=Int32Array.from({length:n.length/2},((t,n)=>n)).sort(((t,e)=>n[2*t]-n[2*e]||n[2*t+1]-n[2*e+1]));const t=this.collinear[0],e=this.collinear[this.collinear.length-1],r=[n[2*t],n[2*t+1],n[2*e],n[2*e+1]],i=1e-8*Math.hypot(r[3]-r[1],r[2]-r[0]);for(let t=0,e=n.length/2;t0&&(this.triangles=new Int32Array(3).fill(-1),this.halfedges=new Int32Array(3).fill(-1),this.triangles[0]=r[0],o[r[0]]=1,2===r.length&&(o[r[1]]=0,this.triangles[1]=r[1],this.triangles[2]=r[1]))}voronoi(t){return new qu(this,t)}*neighbors(t){const{inedges:n,hull:e,_hullIndex:r,halfedges:i,triangles:o,collinear:a}=this;if(a){const n=a.indexOf(t);return n>0&&(yield a[n-1]),void(n=0&&i!==e&&i!==r;)e=i;return i}_step(t,n,e){const{inedges:r,hull:i,_hullIndex:o,halfedges:a,triangles:u,points:c}=this;if(-1===r[t]||!c.length)return(t+1)%(c.length>>1);let f=t,s=Iu(n-c[2*t],2)+Iu(e-c[2*t+1],2);const l=r[t];let h=l;do{let r=u[h];const l=Iu(n-c[2*r],2)+Iu(e-c[2*r+1],2);if(l9999?"+"+Ku(n,6):Ku(n,4))+"-"+Ku(t.getUTCMonth()+1,2)+"-"+Ku(t.getUTCDate(),2)+(o?"T"+Ku(e,2)+":"+Ku(r,2)+":"+Ku(i,2)+"."+Ku(o,3)+"Z":i?"T"+Ku(e,2)+":"+Ku(r,2)+":"+Ku(i,2)+"Z":r||e?"T"+Ku(e,2)+":"+Ku(r,2)+"Z":"")}function Ju(t){var n=new RegExp('["'+t+"\n\r]"),e=t.charCodeAt(0);function r(t,n){var r,i=[],o=t.length,a=0,u=0,c=o<=0,f=!1;function s(){if(c)return Hu;if(f)return f=!1,ju;var n,r,i=a;if(t.charCodeAt(i)===Xu){for(;a++=o?c=!0:(r=t.charCodeAt(a++))===Gu?f=!0:r===Vu&&(f=!0,t.charCodeAt(a)===Gu&&++a),t.slice(i+1,n-1).replace(/""/g,'"')}for(;amc(n,e).then((n=>(new DOMParser).parseFromString(n,t)))}var Sc=Ac("application/xml"),Ec=Ac("text/html"),Nc=Ac("image/svg+xml");function kc(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,a,u,c,f,s,l,h,d=t._root,p={data:r},g=t._x0,y=t._y0,v=t._x1,_=t._y1;if(!d)return t._root=p,t;for(;d.length;)if((f=n>=(o=(g+v)/2))?g=o:v=o,(s=e>=(a=(y+_)/2))?y=a:_=a,i=d,!(d=d[l=s<<1|f]))return i[l]=p,t;if(u=+t._x.call(null,d.data),c=+t._y.call(null,d.data),n===u&&e===c)return p.next=d,i?i[l]=p:t._root=p,t;do{i=i?i[l]=new Array(4):t._root=new Array(4),(f=n>=(o=(g+v)/2))?g=o:v=o,(s=e>=(a=(y+_)/2))?y=a:_=a}while((l=s<<1|f)==(h=(c>=a)<<1|u>=o));return i[h]=d,i[l]=p,t}function Cc(t,n,e,r,i){this.node=t,this.x0=n,this.y0=e,this.x1=r,this.y1=i}function Pc(t){return t[0]}function zc(t){return t[1]}function $c(t,n,e){var r=new Dc(null==n?Pc:n,null==e?zc:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Dc(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function Rc(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}var Fc=$c.prototype=Dc.prototype;function qc(t){return function(){return t}}function Uc(t){return 1e-6*(t()-.5)}function Ic(t){return t.x+t.vx}function Oc(t){return t.y+t.vy}function Bc(t){return t.index}function Yc(t,n){var e=t.get(n);if(!e)throw new Error("node not found: "+n);return e}Fc.copy=function(){var t,n,e=new Dc(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return e;if(!r.length)return e._root=Rc(r),e;for(t=[{source:r,target:e._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(4)}):r.target[i]=Rc(n));return e},Fc.add=function(t){const n=+this._x.call(null,t),e=+this._y.call(null,t);return kc(this.cover(n,e),n,e,t)},Fc.addAll=function(t){var n,e,r,i,o=t.length,a=new Array(o),u=new Array(o),c=1/0,f=1/0,s=-1/0,l=-1/0;for(e=0;es&&(s=r),il&&(l=i));if(c>s||f>l)return this;for(this.cover(c,f).cover(s,l),e=0;et||t>=i||r>n||n>=o;)switch(u=(nh||(o=c.y0)>d||(a=c.x1)=v)<<1|t>=y)&&(c=p[p.length-1],p[p.length-1]=p[p.length-1-f],p[p.length-1-f]=c)}else{var _=t-+this._x.call(null,g.data),b=n-+this._y.call(null,g.data),m=_*_+b*b;if(m=(u=(p+y)/2))?p=u:y=u,(s=a>=(c=(g+v)/2))?g=c:v=c,n=d,!(d=d[l=s<<1|f]))return this;if(!d.length)break;(n[l+1&3]||n[l+2&3]||n[l+3&3])&&(e=n,h=l)}for(;d.data!==t;)if(r=d,!(d=d.next))return this;return(i=d.next)&&delete d.next,r?(i?r.next=i:delete r.next,this):n?(i?n[l]=i:delete n[l],(d=n[0]||n[1]||n[2]||n[3])&&d===(n[3]||n[2]||n[1]||n[0])&&!d.length&&(e?e[h]=d:this._root=d),this):(this._root=i,this)},Fc.removeAll=function(t){for(var n=0,e=t.length;n1?r[0]+r.slice(2):r,+t.slice(e+1)]}function Zc(t){return(t=Wc(Math.abs(t)))?t[1]:NaN}var Kc,Qc=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function Jc(t){if(!(n=Qc.exec(t)))throw new Error("invalid format: "+t);var n;return new tf({fill:n[1],align:n[2],sign:n[3],symbol:n[4],zero:n[5],width:n[6],comma:n[7],precision:n[8]&&n[8].slice(1),trim:n[9],type:n[10]})}function tf(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function nf(t,n){var e=Wc(t,n);if(!e)return t+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}Jc.prototype=tf.prototype,tf.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};var ef={"%":(t,n)=>(100*t).toFixed(n),b:t=>Math.round(t).toString(2),c:t=>t+"",d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:(t,n)=>t.toExponential(n),f:(t,n)=>t.toFixed(n),g:(t,n)=>t.toPrecision(n),o:t=>Math.round(t).toString(8),p:(t,n)=>nf(100*t,n),r:nf,s:function(t,n){var e=Wc(t,n);if(!e)return t+"";var r=e[0],i=e[1],o=i-(Kc=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,a=r.length;return o===a?r:o>a?r+new Array(o-a+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+Wc(t,Math.max(0,n+o-1))[0]},X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function rf(t){return t}var of,af=Array.prototype.map,uf=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function cf(t){var n,e,r=void 0===t.grouping||void 0===t.thousands?rf:(n=af.call(t.grouping,Number),e=t.thousands+"",function(t,r){for(var i=t.length,o=[],a=0,u=n[0],c=0;i>0&&u>0&&(c+u+1>r&&(u=Math.max(1,r-c)),o.push(t.substring(i-=u,i+u)),!((c+=u+1)>r));)u=n[a=(a+1)%n.length];return o.reverse().join(e)}),i=void 0===t.currency?"":t.currency[0]+"",o=void 0===t.currency?"":t.currency[1]+"",a=void 0===t.decimal?".":t.decimal+"",u=void 0===t.numerals?rf:function(t){return function(n){return n.replace(/[0-9]/g,(function(n){return t[+n]}))}}(af.call(t.numerals,String)),c=void 0===t.percent?"%":t.percent+"",f=void 0===t.minus?"−":t.minus+"",s=void 0===t.nan?"NaN":t.nan+"";function l(t){var n=(t=Jc(t)).fill,e=t.align,l=t.sign,h=t.symbol,d=t.zero,p=t.width,g=t.comma,y=t.precision,v=t.trim,_=t.type;"n"===_?(g=!0,_="g"):ef[_]||(void 0===y&&(y=12),v=!0,_="g"),(d||"0"===n&&"="===e)&&(d=!0,n="0",e="=");var b="$"===h?i:"#"===h&&/[boxX]/.test(_)?"0"+_.toLowerCase():"",m="$"===h?o:/[%p]/.test(_)?c:"",x=ef[_],w=/[defgprs%]/.test(_);function M(t){var i,o,c,h=b,M=m;if("c"===_)M=x(t)+M,t="";else{var T=(t=+t)<0||1/t<0;if(t=isNaN(t)?s:x(Math.abs(t),y),v&&(t=function(t){t:for(var n,e=t.length,r=1,i=-1;r0&&(i=0)}return i>0?t.slice(0,i)+t.slice(n+1):t}(t)),T&&0==+t&&"+"!==l&&(T=!1),h=(T?"("===l?l:f:"-"===l||"("===l?"":l)+h,M=("s"===_?uf[8+Kc/3]:"")+M+(T&&"("===l?")":""),w)for(i=-1,o=t.length;++i(c=t.charCodeAt(i))||c>57){M=(46===c?a+t.slice(i+1):t.slice(i))+M,t=t.slice(0,i);break}}g&&!d&&(t=r(t,1/0));var A=h.length+t.length+M.length,S=A>1)+h+t+M+S.slice(A);break;default:t=S+h+t+M}return u(t)}return y=void 0===y?6:/[gprs]/.test(_)?Math.max(1,Math.min(21,y)):Math.max(0,Math.min(20,y)),M.toString=function(){return t+""},M}return{format:l,formatPrefix:function(t,n){var e=l(((t=Jc(t)).type="f",t)),r=3*Math.max(-8,Math.min(8,Math.floor(Zc(n)/3))),i=Math.pow(10,-r),o=uf[8+r/3];return function(t){return e(i*t)+o}}}}function ff(n){return of=cf(n),t.format=of.format,t.formatPrefix=of.formatPrefix,of}function sf(t){return Math.max(0,-Zc(Math.abs(t)))}function lf(t,n){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(Zc(n)/3)))-Zc(Math.abs(t)))}function hf(t,n){return t=Math.abs(t),n=Math.abs(n)-t,Math.max(0,Zc(n)-Zc(t))+1}t.format=void 0,t.formatPrefix=void 0,ff({thousands:",",grouping:[3],currency:["$",""]});var df=1e-6,pf=1e-12,gf=Math.PI,yf=gf/2,vf=gf/4,_f=2*gf,bf=180/gf,mf=gf/180,xf=Math.abs,wf=Math.atan,Mf=Math.atan2,Tf=Math.cos,Af=Math.ceil,Sf=Math.exp,Ef=Math.hypot,Nf=Math.log,kf=Math.pow,Cf=Math.sin,Pf=Math.sign||function(t){return t>0?1:t<0?-1:0},zf=Math.sqrt,$f=Math.tan;function Df(t){return t>1?0:t<-1?gf:Math.acos(t)}function Rf(t){return t>1?yf:t<-1?-yf:Math.asin(t)}function Ff(t){return(t=Cf(t/2))*t}function qf(){}function Uf(t,n){t&&Of.hasOwnProperty(t.type)&&Of[t.type](t,n)}var If={Feature:function(t,n){Uf(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r=0?1:-1,i=r*e,o=Tf(n=(n*=mf)/2+vf),a=Cf(n),u=Vf*a,c=Gf*o+u*Tf(i),f=u*r*Cf(i);as.add(Mf(f,c)),Xf=t,Gf=o,Vf=a}function ds(t){return[Mf(t[1],t[0]),Rf(t[2])]}function ps(t){var n=t[0],e=t[1],r=Tf(e);return[r*Tf(n),r*Cf(n),Cf(e)]}function gs(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function ys(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function vs(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function _s(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function bs(t){var n=zf(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}var ms,xs,ws,Ms,Ts,As,Ss,Es,Ns,ks,Cs,Ps,zs,$s,Ds,Rs,Fs={point:qs,lineStart:Is,lineEnd:Os,polygonStart:function(){Fs.point=Bs,Fs.lineStart=Ys,Fs.lineEnd=Ls,rs=new T,cs.polygonStart()},polygonEnd:function(){cs.polygonEnd(),Fs.point=qs,Fs.lineStart=Is,Fs.lineEnd=Os,as<0?(Wf=-(Kf=180),Zf=-(Qf=90)):rs>df?Qf=90:rs<-df&&(Zf=-90),os[0]=Wf,os[1]=Kf},sphere:function(){Wf=-(Kf=180),Zf=-(Qf=90)}};function qs(t,n){is.push(os=[Wf=t,Kf=t]),nQf&&(Qf=n)}function Us(t,n){var e=ps([t*mf,n*mf]);if(es){var r=ys(es,e),i=ys([r[1],-r[0],0],r);bs(i),i=ds(i);var o,a=t-Jf,u=a>0?1:-1,c=i[0]*bf*u,f=xf(a)>180;f^(u*JfQf&&(Qf=o):f^(u*Jf<(c=(c+360)%360-180)&&cQf&&(Qf=n)),f?tjs(Wf,Kf)&&(Kf=t):js(t,Kf)>js(Wf,Kf)&&(Wf=t):Kf>=Wf?(tKf&&(Kf=t)):t>Jf?js(Wf,t)>js(Wf,Kf)&&(Kf=t):js(t,Kf)>js(Wf,Kf)&&(Wf=t)}else is.push(os=[Wf=t,Kf=t]);nQf&&(Qf=n),es=e,Jf=t}function Is(){Fs.point=Us}function Os(){os[0]=Wf,os[1]=Kf,Fs.point=qs,es=null}function Bs(t,n){if(es){var e=t-Jf;rs.add(xf(e)>180?e+(e>0?360:-360):e)}else ts=t,ns=n;cs.point(t,n),Us(t,n)}function Ys(){cs.lineStart()}function Ls(){Bs(ts,ns),cs.lineEnd(),xf(rs)>df&&(Wf=-(Kf=180)),os[0]=Wf,os[1]=Kf,es=null}function js(t,n){return(n-=t)<0?n+360:n}function Hs(t,n){return t[0]-n[0]}function Xs(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:ngf&&(t-=Math.round(t/_f)*_f),[t,n]}function ul(t,n,e){return(t%=_f)?n||e?ol(fl(t),sl(n,e)):fl(t):n||e?sl(n,e):al}function cl(t){return function(n,e){return xf(n+=t)>gf&&(n-=Math.round(n/_f)*_f),[n,e]}}function fl(t){var n=cl(t);return n.invert=cl(-t),n}function sl(t,n){var e=Tf(t),r=Cf(t),i=Tf(n),o=Cf(n);function a(t,n){var a=Tf(n),u=Tf(t)*a,c=Cf(t)*a,f=Cf(n),s=f*e+u*r;return[Mf(c*i-s*o,u*e-f*r),Rf(s*i+c*o)]}return a.invert=function(t,n){var a=Tf(n),u=Tf(t)*a,c=Cf(t)*a,f=Cf(n),s=f*i-c*o;return[Mf(c*i+f*o,u*e+s*r),Rf(s*e-u*r)]},a}function ll(t){function n(n){return(n=t(n[0]*mf,n[1]*mf))[0]*=bf,n[1]*=bf,n}return t=ul(t[0]*mf,t[1]*mf,t.length>2?t[2]*mf:0),n.invert=function(n){return(n=t.invert(n[0]*mf,n[1]*mf))[0]*=bf,n[1]*=bf,n},n}function hl(t,n,e,r,i,o){if(e){var a=Tf(n),u=Cf(n),c=r*e;null==i?(i=n+r*_f,o=n-c/2):(i=dl(a,i),o=dl(a,o),(r>0?io)&&(i+=r*_f));for(var f,s=i;r>0?s>o:s1&&n.push(n.pop().concat(n.shift()))},result:function(){var e=n;return n=[],t=null,e}}}function gl(t,n){return xf(t[0]-n[0])=0;--o)i.point((s=f[o])[0],s[1]);else r(h.x,h.p.x,-1,i);h=h.p}f=(h=h.o).z,d=!d}while(!h.v);i.lineEnd()}}}function _l(t){if(n=t.length){for(var n,e,r=0,i=t[0];++r=0?1:-1,E=S*A,N=E>gf,k=y*w;if(c.add(Mf(k*S*Cf(E),v*M+k*Tf(E))),a+=N?A+S*_f:A,N^p>=e^m>=e){var C=ys(ps(d),ps(b));bs(C);var P=ys(o,C);bs(P);var z=(N^A>=0?-1:1)*Rf(P[2]);(r>z||r===z&&(C[0]||C[1]))&&(u+=N^A>=0?1:-1)}}return(a<-df||a0){for(l||(i.polygonStart(),l=!0),i.lineStart(),t=0;t1&&2&c&&h.push(h.pop().concat(h.shift())),a.push(h.filter(wl))}return h}}function wl(t){return t.length>1}function Ml(t,n){return((t=t.x)[0]<0?t[1]-yf-df:yf-t[1])-((n=n.x)[0]<0?n[1]-yf-df:yf-n[1])}al.invert=al;var Tl=xl((function(){return!0}),(function(t){var n,e=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lineStart(),n=1},point:function(o,a){var u=o>0?gf:-gf,c=xf(o-e);xf(c-gf)0?yf:-yf),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(u,r),t.point(o,r),n=0):i!==u&&c>=gf&&(xf(e-i)df?wf((Cf(n)*(o=Tf(r))*Cf(e)-Cf(r)*(i=Tf(n))*Cf(t))/(i*o*a)):(n+r)/2}(e,r,o,a),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(u,r),n=0),t.point(e=o,r=a),i=u},lineEnd:function(){t.lineEnd(),e=r=NaN},clean:function(){return 2-n}}}),(function(t,n,e,r){var i;if(null==t)i=e*yf,r.point(-gf,i),r.point(0,i),r.point(gf,i),r.point(gf,0),r.point(gf,-i),r.point(0,-i),r.point(-gf,-i),r.point(-gf,0),r.point(-gf,i);else if(xf(t[0]-n[0])>df){var o=t[0]0,i=xf(n)>df;function o(t,e){return Tf(t)*Tf(e)>n}function a(t,e,r){var i=[1,0,0],o=ys(ps(t),ps(e)),a=gs(o,o),u=o[0],c=a-u*u;if(!c)return!r&&t;var f=n*a/c,s=-n*u/c,l=ys(i,o),h=_s(i,f);vs(h,_s(o,s));var d=l,p=gs(h,d),g=gs(d,d),y=p*p-g*(gs(h,h)-1);if(!(y<0)){var v=zf(y),_=_s(d,(-p-v)/g);if(vs(_,h),_=ds(_),!r)return _;var b,m=t[0],x=e[0],w=t[1],M=e[1];x0^_[1]<(xf(_[0]-m)gf^(m<=_[0]&&_[0]<=x)){var S=_s(d,(-p+v)/g);return vs(S,h),[_,ds(S)]}}}function u(n,e){var i=r?t:gf-t,o=0;return n<-i?o|=1:n>i&&(o|=2),e<-i?o|=4:e>i&&(o|=8),o}return xl(o,(function(t){var n,e,c,f,s;return{lineStart:function(){f=c=!1,s=1},point:function(l,h){var d,p=[l,h],g=o(l,h),y=r?g?0:u(l,h):g?u(l+(l<0?gf:-gf),h):0;if(!n&&(f=c=g)&&t.lineStart(),g!==c&&(!(d=a(n,p))||gl(n,d)||gl(p,d))&&(p[2]=1),g!==c)s=0,g?(t.lineStart(),d=a(p,n),t.point(d[0],d[1])):(d=a(n,p),t.point(d[0],d[1],2),t.lineEnd()),n=d;else if(i&&n&&r^g){var v;y&e||!(v=a(p,n,!0))||(s=0,r?(t.lineStart(),t.point(v[0][0],v[0][1]),t.point(v[1][0],v[1][1]),t.lineEnd()):(t.point(v[1][0],v[1][1]),t.lineEnd(),t.lineStart(),t.point(v[0][0],v[0][1],3)))}!g||n&&gl(n,p)||t.point(p[0],p[1]),n=p,c=g,e=y},lineEnd:function(){c&&t.lineEnd(),n=null},clean:function(){return s|(f&&c)<<1}}}),(function(n,r,i,o){hl(o,t,e,i,n,r)}),r?[0,-t]:[-gf,t-gf])}var Sl,El,Nl,kl,Cl=1e9,Pl=-Cl;function zl(t,n,e,r){function i(i,o){return t<=i&&i<=e&&n<=o&&o<=r}function o(i,o,u,f){var s=0,l=0;if(null==i||(s=a(i,u))!==(l=a(o,u))||c(i,o)<0^u>0)do{f.point(0===s||3===s?t:e,s>1?r:n)}while((s=(s+u+4)%4)!==l);else f.point(o[0],o[1])}function a(r,i){return xf(r[0]-t)0?0:3:xf(r[0]-e)0?2:1:xf(r[1]-n)0?1:0:i>0?3:2}function u(t,n){return c(t.x,n.x)}function c(t,n){var e=a(t,1),r=a(n,1);return e!==r?e-r:0===e?n[1]-t[1]:1===e?t[0]-n[0]:2===e?t[1]-n[1]:n[0]-t[0]}return function(a){var c,f,s,l,h,d,p,g,y,v,_,b=a,m=pl(),x={point:w,lineStart:function(){x.point=M,f&&f.push(s=[]);v=!0,y=!1,p=g=NaN},lineEnd:function(){c&&(M(l,h),d&&y&&m.rejoin(),c.push(m.result()));x.point=w,y&&b.lineEnd()},polygonStart:function(){b=m,c=[],f=[],_=!0},polygonEnd:function(){var n=function(){for(var n=0,e=0,i=f.length;er&&(h-o)*(r-a)>(d-a)*(t-o)&&++n:d<=r&&(h-o)*(r-a)<(d-a)*(t-o)&&--n;return n}(),e=_&&n,i=(c=ft(c)).length;(e||i)&&(a.polygonStart(),e&&(a.lineStart(),o(null,null,1,a),a.lineEnd()),i&&vl(c,u,n,o,a),a.polygonEnd());b=a,c=f=s=null}};function w(t,n){i(t,n)&&b.point(t,n)}function M(o,a){var u=i(o,a);if(f&&s.push([o,a]),v)l=o,h=a,d=u,v=!1,u&&(b.lineStart(),b.point(o,a));else if(u&&y)b.point(o,a);else{var c=[p=Math.max(Pl,Math.min(Cl,p)),g=Math.max(Pl,Math.min(Cl,g))],m=[o=Math.max(Pl,Math.min(Cl,o)),a=Math.max(Pl,Math.min(Cl,a))];!function(t,n,e,r,i,o){var a,u=t[0],c=t[1],f=0,s=1,l=n[0]-u,h=n[1]-c;if(a=e-u,l||!(a>0)){if(a/=l,l<0){if(a0){if(a>s)return;a>f&&(f=a)}if(a=i-u,l||!(a<0)){if(a/=l,l<0){if(a>s)return;a>f&&(f=a)}else if(l>0){if(a0)){if(a/=h,h<0){if(a0){if(a>s)return;a>f&&(f=a)}if(a=o-c,h||!(a<0)){if(a/=h,h<0){if(a>s)return;a>f&&(f=a)}else if(h>0){if(a0&&(t[0]=u+f*l,t[1]=c+f*h),s<1&&(n[0]=u+s*l,n[1]=c+s*h),!0}}}}}(c,m,t,n,e,r)?u&&(b.lineStart(),b.point(o,a),_=!1):(y||(b.lineStart(),b.point(c[0],c[1])),b.point(m[0],m[1]),u||b.lineEnd(),_=!1)}p=o,g=a,y=u}return x}}var $l={sphere:qf,point:qf,lineStart:function(){$l.point=Rl,$l.lineEnd=Dl},lineEnd:qf,polygonStart:qf,polygonEnd:qf};function Dl(){$l.point=$l.lineEnd=qf}function Rl(t,n){El=t*=mf,Nl=Cf(n*=mf),kl=Tf(n),$l.point=Fl}function Fl(t,n){t*=mf;var e=Cf(n*=mf),r=Tf(n),i=xf(t-El),o=Tf(i),a=r*Cf(i),u=kl*e-Nl*r*o,c=Nl*e+kl*r*o;Sl.add(Mf(zf(a*a+u*u),c)),El=t,Nl=e,kl=r}function ql(t){return Sl=new T,Lf(t,$l),+Sl}var Ul=[null,null],Il={type:"LineString",coordinates:Ul};function Ol(t,n){return Ul[0]=t,Ul[1]=n,ql(Il)}var Bl={Feature:function(t,n){return Ll(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r0&&(i=Ol(t[o],t[o-1]))>0&&e<=i&&r<=i&&(e+r-i)*(1-Math.pow((e-r)/i,2))df})).map(c)).concat(lt(Af(o/d)*d,i,d).filter((function(t){return xf(t%g)>df})).map(f))}return v.lines=function(){return _().map((function(t){return{type:"LineString",coordinates:t}}))},v.outline=function(){return{type:"Polygon",coordinates:[s(r).concat(l(a).slice(1),s(e).reverse().slice(1),l(u).reverse().slice(1))]}},v.extent=function(t){return arguments.length?v.extentMajor(t).extentMinor(t):v.extentMinor()},v.extentMajor=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],u=+t[0][1],a=+t[1][1],r>e&&(t=r,r=e,e=t),u>a&&(t=u,u=a,a=t),v.precision(y)):[[r,u],[e,a]]},v.extentMinor=function(e){return arguments.length?(n=+e[0][0],t=+e[1][0],o=+e[0][1],i=+e[1][1],n>t&&(e=n,n=t,t=e),o>i&&(e=o,o=i,i=e),v.precision(y)):[[n,o],[t,i]]},v.step=function(t){return arguments.length?v.stepMajor(t).stepMinor(t):v.stepMinor()},v.stepMajor=function(t){return arguments.length?(p=+t[0],g=+t[1],v):[p,g]},v.stepMinor=function(t){return arguments.length?(h=+t[0],d=+t[1],v):[h,d]},v.precision=function(h){return arguments.length?(y=+h,c=Wl(o,i,90),f=Zl(n,t,y),s=Wl(u,a,90),l=Zl(r,e,y),v):y},v.extentMajor([[-180,-90+df],[180,90-df]]).extentMinor([[-180,-80-df],[180,80+df]])}var Ql,Jl,th,nh,eh=t=>t,rh=new T,ih=new T,oh={point:qf,lineStart:qf,lineEnd:qf,polygonStart:function(){oh.lineStart=ah,oh.lineEnd=fh},polygonEnd:function(){oh.lineStart=oh.lineEnd=oh.point=qf,rh.add(xf(ih)),ih=new T},result:function(){var t=rh/2;return rh=new T,t}};function ah(){oh.point=uh}function uh(t,n){oh.point=ch,Ql=th=t,Jl=nh=n}function ch(t,n){ih.add(nh*t-th*n),th=t,nh=n}function fh(){ch(Ql,Jl)}var sh=oh,lh=1/0,hh=lh,dh=-lh,ph=dh,gh={point:function(t,n){tdh&&(dh=t);nph&&(ph=n)},lineStart:qf,lineEnd:qf,polygonStart:qf,polygonEnd:qf,result:function(){var t=[[lh,hh],[dh,ph]];return dh=ph=-(hh=lh=1/0),t}};var yh,vh,_h,bh,mh=gh,xh=0,wh=0,Mh=0,Th=0,Ah=0,Sh=0,Eh=0,Nh=0,kh=0,Ch={point:Ph,lineStart:zh,lineEnd:Rh,polygonStart:function(){Ch.lineStart=Fh,Ch.lineEnd=qh},polygonEnd:function(){Ch.point=Ph,Ch.lineStart=zh,Ch.lineEnd=Rh},result:function(){var t=kh?[Eh/kh,Nh/kh]:Sh?[Th/Sh,Ah/Sh]:Mh?[xh/Mh,wh/Mh]:[NaN,NaN];return xh=wh=Mh=Th=Ah=Sh=Eh=Nh=kh=0,t}};function Ph(t,n){xh+=t,wh+=n,++Mh}function zh(){Ch.point=$h}function $h(t,n){Ch.point=Dh,Ph(_h=t,bh=n)}function Dh(t,n){var e=t-_h,r=n-bh,i=zf(e*e+r*r);Th+=i*(_h+t)/2,Ah+=i*(bh+n)/2,Sh+=i,Ph(_h=t,bh=n)}function Rh(){Ch.point=Ph}function Fh(){Ch.point=Uh}function qh(){Ih(yh,vh)}function Uh(t,n){Ch.point=Ih,Ph(yh=_h=t,vh=bh=n)}function Ih(t,n){var e=t-_h,r=n-bh,i=zf(e*e+r*r);Th+=i*(_h+t)/2,Ah+=i*(bh+n)/2,Sh+=i,Eh+=(i=bh*t-_h*n)*(_h+t),Nh+=i*(bh+n),kh+=3*i,Ph(_h=t,bh=n)}var Oh=Ch;function Bh(t){this._context=t}Bh.prototype={_radius:4.5,pointRadius:function(t){return this._radius=t,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._context.closePath(),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._context.moveTo(t,n),this._point=1;break;case 1:this._context.lineTo(t,n);break;default:this._context.moveTo(t+this._radius,n),this._context.arc(t,n,this._radius,0,_f)}},result:qf};var Yh,Lh,jh,Hh,Xh,Gh=new T,Vh={point:qf,lineStart:function(){Vh.point=Wh},lineEnd:function(){Yh&&Zh(Lh,jh),Vh.point=qf},polygonStart:function(){Yh=!0},polygonEnd:function(){Yh=null},result:function(){var t=+Gh;return Gh=new T,t}};function Wh(t,n){Vh.point=Zh,Lh=Hh=t,jh=Xh=n}function Zh(t,n){Hh-=t,Xh-=n,Gh.add(zf(Hh*Hh+Xh*Xh)),Hh=t,Xh=n}var Kh=Vh;let Qh,Jh,td,nd;class ed{constructor(t){this._append=null==t?rd:function(t){const n=Math.floor(t);if(!(n>=0))throw new RangeError(`invalid digits: ${t}`);if(n>15)return rd;if(n!==Qh){const t=10**n;Qh=n,Jh=function(n){let e=1;this._+=n[0];for(const r=n.length;e4*n&&g--){var m=a+h,x=u+d,w=c+p,M=zf(m*m+x*x+w*w),T=Rf(w/=M),A=xf(xf(w)-1)n||xf((v*k+_*C)/b-.5)>.3||a*h+u*d+c*p2?t[2]%360*mf:0,k()):[y*bf,v*bf,_*bf]},E.angle=function(t){return arguments.length?(b=t%360*mf,k()):b*bf},E.reflectX=function(t){return arguments.length?(m=t?-1:1,k()):m<0},E.reflectY=function(t){return arguments.length?(x=t?-1:1,k()):x<0},E.precision=function(t){return arguments.length?(a=dd(u,S=t*t),C()):zf(S)},E.fitExtent=function(t,n){return ud(E,t,n)},E.fitSize=function(t,n){return cd(E,t,n)},E.fitWidth=function(t,n){return fd(E,t,n)},E.fitHeight=function(t,n){return sd(E,t,n)},function(){return n=t.apply(this,arguments),E.invert=n.invert&&N,k()}}function _d(t){var n=0,e=gf/3,r=vd(t),i=r(n,e);return i.parallels=function(t){return arguments.length?r(n=t[0]*mf,e=t[1]*mf):[n*bf,e*bf]},i}function bd(t,n){var e=Cf(t),r=(e+Cf(n))/2;if(xf(r)0?n<-yf+df&&(n=-yf+df):n>yf-df&&(n=yf-df);var e=i/kf(Nd(n),r);return[e*Cf(r*t),i-e*Tf(r*t)]}return o.invert=function(t,n){var e=i-n,o=Pf(r)*zf(t*t+e*e),a=Mf(t,xf(e))*Pf(e);return e*r<0&&(a-=gf*Pf(t)*Pf(e)),[a/r,2*wf(kf(i/o,1/r))-yf]},o}function Cd(t,n){return[t,n]}function Pd(t,n){var e=Tf(t),r=t===n?Cf(t):(e-Tf(n))/(n-t),i=e/r+t;if(xf(r)=0;)n+=e[r].value;else n=1;t.value=n}function Gd(t,n){t instanceof Map?(t=[void 0,t],void 0===n&&(n=Wd)):void 0===n&&(n=Vd);for(var e,r,i,o,a,u=new Qd(t),c=[u];e=c.pop();)if((i=n(e.data))&&(a=(i=Array.from(i)).length))for(e.children=i,o=a-1;o>=0;--o)c.push(r=i[o]=new Qd(i[o])),r.parent=e,r.depth=e.depth+1;return u.eachBefore(Kd)}function Vd(t){return t.children}function Wd(t){return Array.isArray(t)?t[1]:null}function Zd(t){void 0!==t.data.value&&(t.value=t.data.value),t.data=t.data.data}function Kd(t){var n=0;do{t.height=n}while((t=t.parent)&&t.height<++n)}function Qd(t){this.data=t,this.depth=this.height=0,this.parent=null}function Jd(t){return null==t?null:tp(t)}function tp(t){if("function"!=typeof t)throw new Error;return t}function np(){return 0}function ep(t){return function(){return t}}qd.invert=function(t,n){for(var e,r=n,i=r*r,o=i*i*i,a=0;a<12&&(o=(i=(r-=e=(r*(zd+$d*i+o*(Dd+Rd*i))-n)/(zd+3*$d*i+o*(7*Dd+9*Rd*i)))*r)*i*i,!(xf(e)df&&--i>0);return[t/(.8707+(o=r*r)*(o*(o*o*o*(.003971-.001529*o)-.013791)-.131979)),r]},Od.invert=Md(Rf),Bd.invert=Md((function(t){return 2*wf(t)})),Yd.invert=function(t,n){return[-n,2*wf(Sf(t))-yf]},Qd.prototype=Gd.prototype={constructor:Qd,count:function(){return this.eachAfter(Xd)},each:function(t,n){let e=-1;for(const r of this)t.call(n,r,++e,this);return this},eachAfter:function(t,n){for(var e,r,i,o=this,a=[o],u=[],c=-1;o=a.pop();)if(u.push(o),e=o.children)for(r=0,i=e.length;r=0;--r)o.push(e[r]);return this},find:function(t,n){let e=-1;for(const r of this)if(t.call(n,r,++e,this))return r},sum:function(t){return this.eachAfter((function(n){for(var e=+t(n.data)||0,r=n.children,i=r&&r.length;--i>=0;)e+=r[i].value;n.value=e}))},sort:function(t){return this.eachBefore((function(n){n.children&&n.children.sort(t)}))},path:function(t){for(var n=this,e=function(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i=null;t=e.pop(),n=r.pop();for(;t===n;)i=t,t=e.pop(),n=r.pop();return i}(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n},descendants:function(){return Array.from(this)},leaves:function(){var t=[];return this.eachBefore((function(n){n.children||t.push(n)})),t},links:function(){var t=this,n=[];return t.each((function(e){e!==t&&n.push({source:e.parent,target:e})})),n},copy:function(){return Gd(this).eachBefore(Zd)},[Symbol.iterator]:function*(){var t,n,e,r,i=this,o=[i];do{for(t=o.reverse(),o=[];i=t.pop();)if(yield i,n=i.children)for(e=0,r=n.length;e(t=(rp*t+ip)%op)/op}function up(t,n){for(var e,r,i=0,o=(t=function(t,n){let e,r,i=t.length;for(;i;)r=n()*i--|0,e=t[i],t[i]=t[r],t[r]=e;return t}(Array.from(t),n)).length,a=[];i0&&e*e>r*r+i*i}function lp(t,n){for(var e=0;e1e-6?(E+Math.sqrt(E*E-4*S*N))/(2*S):N/E);return{x:r+w+M*k,y:i+T+A*k,r:k}}function gp(t,n,e){var r,i,o,a,u=t.x-n.x,c=t.y-n.y,f=u*u+c*c;f?(i=n.r+e.r,i*=i,a=t.r+e.r,i>(a*=a)?(r=(f+a-i)/(2*f),o=Math.sqrt(Math.max(0,a/f-r*r)),e.x=t.x-r*u-o*c,e.y=t.y-r*c+o*u):(r=(f+i-a)/(2*f),o=Math.sqrt(Math.max(0,i/f-r*r)),e.x=n.x+r*u-o*c,e.y=n.y+r*c+o*u)):(e.x=n.x+e.r,e.y=n.y)}function yp(t,n){var e=t.r+n.r-1e-6,r=n.x-t.x,i=n.y-t.y;return e>0&&e*e>r*r+i*i}function vp(t){var n=t._,e=t.next._,r=n.r+e.r,i=(n.x*e.r+e.x*n.r)/r,o=(n.y*e.r+e.y*n.r)/r;return i*i+o*o}function _p(t){this._=t,this.next=null,this.previous=null}function bp(t,n){if(!(o=(t=function(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}(t)).length))return 0;var e,r,i,o,a,u,c,f,s,l,h;if((e=t[0]).x=0,e.y=0,!(o>1))return e.r;if(r=t[1],e.x=-r.r,r.x=e.r,r.y=0,!(o>2))return e.r+r.r;gp(r,e,i=t[2]),e=new _p(e),r=new _p(r),i=new _p(i),e.next=i.previous=r,r.next=e.previous=i,i.next=r.previous=e;t:for(c=3;c1&&!zp(t,n););return t.slice(0,n)}function zp(t,n){if("/"===t[n]){let e=0;for(;n>0&&"\\"===t[--n];)++e;if(!(1&e))return!0}return!1}function $p(t,n){return t.parent===n.parent?1:2}function Dp(t){var n=t.children;return n?n[0]:t.t}function Rp(t){var n=t.children;return n?n[n.length-1]:t.t}function Fp(t,n,e){var r=e/(n.i-t.i);n.c-=r,n.s+=e,t.c+=r,n.z+=e,n.m+=e}function qp(t,n,e){return t.a.parent===n.parent?t.a:e}function Up(t,n){this._=t,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=n}function Ip(t,n,e,r,i){for(var o,a=t.children,u=-1,c=a.length,f=t.value&&(i-e)/t.value;++uh&&(h=u),y=s*s*g,(d=Math.max(h/y,y/l))>p){s-=u;break}p=d}v.push(a={value:s,dice:c1?n:1)},e}(Op);var Lp=function t(n){function e(t,e,r,i,o){if((a=t._squarify)&&a.ratio===n)for(var a,u,c,f,s,l=-1,h=a.length,d=t.value;++l1?n:1)},e}(Op);function jp(t,n,e){return(n[0]-t[0])*(e[1]-t[1])-(n[1]-t[1])*(e[0]-t[0])}function Hp(t,n){return t[0]-n[0]||t[1]-n[1]}function Xp(t){const n=t.length,e=[0,1];let r,i=2;for(r=2;r1&&jp(t[e[i-2]],t[e[i-1]],t[r])<=0;)--i;e[i++]=r}return e.slice(0,i)}var Gp=Math.random,Vp=function t(n){function e(t,e){return t=null==t?0:+t,e=null==e?1:+e,1===arguments.length?(e=t,t=0):e-=t,function(){return n()*e+t}}return e.source=t,e}(Gp),Wp=function t(n){function e(t,e){return arguments.length<2&&(e=t,t=0),t=Math.floor(t),e=Math.floor(e)-t,function(){return Math.floor(n()*e+t)}}return e.source=t,e}(Gp),Zp=function t(n){function e(t,e){var r,i;return t=null==t?0:+t,e=null==e?1:+e,function(){var o;if(null!=r)o=r,r=null;else do{r=2*n()-1,o=2*n()-1,i=r*r+o*o}while(!i||i>1);return t+e*o*Math.sqrt(-2*Math.log(i)/i)}}return e.source=t,e}(Gp),Kp=function t(n){var e=Zp.source(n);function r(){var t=e.apply(this,arguments);return function(){return Math.exp(t())}}return r.source=t,r}(Gp),Qp=function t(n){function e(t){return(t=+t)<=0?()=>0:function(){for(var e=0,r=t;r>1;--r)e+=n();return e+r*n()}}return e.source=t,e}(Gp),Jp=function t(n){var e=Qp.source(n);function r(t){if(0==(t=+t))return n;var r=e(t);return function(){return r()/t}}return r.source=t,r}(Gp),tg=function t(n){function e(t){return function(){return-Math.log1p(-n())/t}}return e.source=t,e}(Gp),ng=function t(n){function e(t){if((t=+t)<0)throw new RangeError("invalid alpha");return t=1/-t,function(){return Math.pow(1-n(),t)}}return e.source=t,e}(Gp),eg=function t(n){function e(t){if((t=+t)<0||t>1)throw new RangeError("invalid p");return function(){return Math.floor(n()+t)}}return e.source=t,e}(Gp),rg=function t(n){function e(t){if((t=+t)<0||t>1)throw new RangeError("invalid p");return 0===t?()=>1/0:1===t?()=>1:(t=Math.log1p(-t),function(){return 1+Math.floor(Math.log1p(-n())/t)})}return e.source=t,e}(Gp),ig=function t(n){var e=Zp.source(n)();function r(t,r){if((t=+t)<0)throw new RangeError("invalid k");if(0===t)return()=>0;if(r=null==r?1:+r,1===t)return()=>-Math.log1p(-n())*r;var i=(t<1?t+1:t)-1/3,o=1/(3*Math.sqrt(i)),a=t<1?()=>Math.pow(n(),1/t):()=>1;return function(){do{do{var t=e(),u=1+o*t}while(u<=0);u*=u*u;var c=1-n()}while(c>=1-.0331*t*t*t*t&&Math.log(c)>=.5*t*t+i*(1-u+Math.log(u)));return i*u*a()*r}}return r.source=t,r}(Gp),og=function t(n){var e=ig.source(n);function r(t,n){var r=e(t),i=e(n);return function(){var t=r();return 0===t?0:t/(t+i())}}return r.source=t,r}(Gp),ag=function t(n){var e=rg.source(n),r=og.source(n);function i(t,n){return t=+t,(n=+n)>=1?()=>t:n<=0?()=>0:function(){for(var i=0,o=t,a=n;o*a>16&&o*(1-a)>16;){var u=Math.floor((o+1)*a),c=r(u,o-u+1)();c<=a?(i+=u,o-=u,a=(a-c)/(1-c)):(o=u-1,a/=c)}for(var f=a<.5,s=e(f?a:1-a),l=s(),h=0;l<=o;++h)l+=s();return i+(f?h:o-h)}}return i.source=t,i}(Gp),ug=function t(n){function e(t,e,r){var i;return 0==(t=+t)?i=t=>-Math.log(t):(t=1/t,i=n=>Math.pow(n,t)),e=null==e?0:+e,r=null==r?1:+r,function(){return e+r*i(-Math.log1p(-n()))}}return e.source=t,e}(Gp),cg=function t(n){function e(t,e){return t=null==t?0:+t,e=null==e?1:+e,function(){return t+e*Math.tan(Math.PI*n())}}return e.source=t,e}(Gp),fg=function t(n){function e(t,e){return t=null==t?0:+t,e=null==e?1:+e,function(){var r=n();return t+e*Math.log(r/(1-r))}}return e.source=t,e}(Gp),sg=function t(n){var e=ig.source(n),r=ag.source(n);function i(t){return function(){for(var i=0,o=t;o>16;){var a=Math.floor(.875*o),u=e(a)();if(u>o)return i+r(a-1,o/u)();i+=a,o-=u}for(var c=-Math.log1p(-n()),f=0;c<=o;++f)c-=Math.log1p(-n());return i+f}}return i.source=t,i}(Gp);const lg=1/4294967296;function hg(t,n){switch(arguments.length){case 0:break;case 1:this.range(t);break;default:this.range(n).domain(t)}return this}function dg(t,n){switch(arguments.length){case 0:break;case 1:"function"==typeof t?this.interpolator(t):this.range(t);break;default:this.domain(t),"function"==typeof n?this.interpolator(n):this.range(n)}return this}const pg=Symbol("implicit");function gg(){var t=new InternMap,n=[],e=[],r=pg;function i(i){let o=t.get(i);if(void 0===o){if(r!==pg)return r;t.set(i,o=n.push(i)-1)}return e[o%e.length]}return i.domain=function(e){if(!arguments.length)return n.slice();n=[],t=new InternMap;for(const r of e)t.has(r)||t.set(r,n.push(r)-1);return i},i.range=function(t){return arguments.length?(e=Array.from(t),i):e.slice()},i.unknown=function(t){return arguments.length?(r=t,i):r},i.copy=function(){return gg(n,e).unknown(r)},hg.apply(i,arguments),i}function yg(){var t,n,e=gg().unknown(void 0),r=e.domain,i=e.range,o=0,a=1,u=!1,c=0,f=0,s=.5;function l(){var e=r().length,l=an&&(e=t,t=n,n=e),function(e){return Math.max(t,Math.min(n,e))}}(a[0],a[t-1])),r=t>2?Mg:wg,i=o=null,l}function l(n){return null==n||isNaN(n=+n)?e:(i||(i=r(a.map(t),u,c)))(t(f(n)))}return l.invert=function(e){return f(n((o||(o=r(u,a.map(t),Yr)))(e)))},l.domain=function(t){return arguments.length?(a=Array.from(t,_g),s()):a.slice()},l.range=function(t){return arguments.length?(u=Array.from(t),s()):u.slice()},l.rangeRound=function(t){return u=Array.from(t),c=Vr,s()},l.clamp=function(t){return arguments.length?(f=!!t||mg,s()):f!==mg},l.interpolate=function(t){return arguments.length?(c=t,s()):c},l.unknown=function(t){return arguments.length?(e=t,l):e},function(e,r){return t=e,n=r,s()}}function Sg(){return Ag()(mg,mg)}function Eg(n,e,r,i){var o,a=W(n,e,r);switch((i=Jc(null==i?",f":i)).type){case"s":var u=Math.max(Math.abs(n),Math.abs(e));return null!=i.precision||isNaN(o=lf(a,u))||(i.precision=o),t.formatPrefix(i,u);case"":case"e":case"g":case"p":case"r":null!=i.precision||isNaN(o=hf(a,Math.max(Math.abs(n),Math.abs(e))))||(i.precision=o-("e"===i.type));break;case"f":case"%":null!=i.precision||isNaN(o=sf(a))||(i.precision=o-2*("%"===i.type))}return t.format(i)}function Ng(t){var n=t.domain;return t.ticks=function(t){var e=n();return G(e[0],e[e.length-1],null==t?10:t)},t.tickFormat=function(t,e){var r=n();return Eg(r[0],r[r.length-1],null==t?10:t,e)},t.nice=function(e){null==e&&(e=10);var r,i,o=n(),a=0,u=o.length-1,c=o[a],f=o[u],s=10;for(f0;){if((i=V(c,f,e))===r)return o[a]=c,o[u]=f,n(o);if(i>0)c=Math.floor(c/i)*i,f=Math.ceil(f/i)*i;else{if(!(i<0))break;c=Math.ceil(c*i)/i,f=Math.floor(f*i)/i}r=i}return t},t}function kg(t,n){var e,r=0,i=(t=t.slice()).length-1,o=t[r],a=t[i];return a-t(-n,e)}function Fg(n){const e=n(Cg,Pg),r=e.domain;let i,o,a=10;function u(){return i=function(t){return t===Math.E?Math.log:10===t&&Math.log10||2===t&&Math.log2||(t=Math.log(t),n=>Math.log(n)/t)}(a),o=function(t){return 10===t?Dg:t===Math.E?Math.exp:n=>Math.pow(t,n)}(a),r()[0]<0?(i=Rg(i),o=Rg(o),n(zg,$g)):n(Cg,Pg),e}return e.base=function(t){return arguments.length?(a=+t,u()):a},e.domain=function(t){return arguments.length?(r(t),u()):r()},e.ticks=t=>{const n=r();let e=n[0],u=n[n.length-1];const c=u0){for(;l<=h;++l)for(f=1;fu)break;p.push(s)}}else for(;l<=h;++l)for(f=a-1;f>=1;--f)if(s=l>0?f/o(-l):f*o(l),!(su)break;p.push(s)}2*p.length{if(null==n&&(n=10),null==r&&(r=10===a?"s":","),"function"!=typeof r&&(a%1||null!=(r=Jc(r)).precision||(r.trim=!0),r=t.format(r)),n===1/0)return r;const u=Math.max(1,a*n/e.ticks().length);return t=>{let n=t/o(Math.round(i(t)));return n*ar(kg(r(),{floor:t=>o(Math.floor(i(t))),ceil:t=>o(Math.ceil(i(t)))})),e}function qg(t){return function(n){return Math.sign(n)*Math.log1p(Math.abs(n/t))}}function Ug(t){return function(n){return Math.sign(n)*Math.expm1(Math.abs(n))*t}}function Ig(t){var n=1,e=t(qg(n),Ug(n));return e.constant=function(e){return arguments.length?t(qg(n=+e),Ug(n)):n},Ng(e)}function Og(t){return function(n){return n<0?-Math.pow(-n,t):Math.pow(n,t)}}function Bg(t){return t<0?-Math.sqrt(-t):Math.sqrt(t)}function Yg(t){return t<0?-t*t:t*t}function Lg(t){var n=t(mg,mg),e=1;return n.exponent=function(n){return arguments.length?1===(e=+n)?t(mg,mg):.5===e?t(Bg,Yg):t(Og(e),Og(1/e)):e},Ng(n)}function jg(){var t=Lg(Ag());return t.copy=function(){return Tg(t,jg()).exponent(t.exponent())},hg.apply(t,arguments),t}function Hg(t){return Math.sign(t)*t*t}const Xg=new Date,Gg=new Date;function Vg(t,n,e,r){function i(n){return t(n=0===arguments.length?new Date:new Date(+n)),n}return i.floor=n=>(t(n=new Date(+n)),n),i.ceil=e=>(t(e=new Date(e-1)),n(e,1),t(e),e),i.round=t=>{const n=i(t),e=i.ceil(t);return t-n(n(t=new Date(+t),null==e?1:Math.floor(e)),t),i.range=(e,r,o)=>{const a=[];if(e=i.ceil(e),o=null==o?1:Math.floor(o),!(e0))return a;let u;do{a.push(u=new Date(+e)),n(e,o),t(e)}while(uVg((n=>{if(n>=n)for(;t(n),!e(n);)n.setTime(n-1)}),((t,r)=>{if(t>=t)if(r<0)for(;++r<=0;)for(;n(t,-1),!e(t););else for(;--r>=0;)for(;n(t,1),!e(t););})),e&&(i.count=(n,r)=>(Xg.setTime(+n),Gg.setTime(+r),t(Xg),t(Gg),Math.floor(e(Xg,Gg))),i.every=t=>(t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?n=>r(n)%t==0:n=>i.count(0,n)%t==0):i:null)),i}const Wg=Vg((()=>{}),((t,n)=>{t.setTime(+t+n)}),((t,n)=>n-t));Wg.every=t=>(t=Math.floor(t),isFinite(t)&&t>0?t>1?Vg((n=>{n.setTime(Math.floor(n/t)*t)}),((n,e)=>{n.setTime(+n+e*t)}),((n,e)=>(e-n)/t)):Wg:null);const Zg=Wg.range,Kg=1e3,Qg=6e4,Jg=36e5,ty=864e5,ny=6048e5,ey=2592e6,ry=31536e6,iy=Vg((t=>{t.setTime(t-t.getMilliseconds())}),((t,n)=>{t.setTime(+t+n*Kg)}),((t,n)=>(n-t)/Kg),(t=>t.getUTCSeconds())),oy=iy.range,ay=Vg((t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*Kg)}),((t,n)=>{t.setTime(+t+n*Qg)}),((t,n)=>(n-t)/Qg),(t=>t.getMinutes())),uy=ay.range,cy=Vg((t=>{t.setUTCSeconds(0,0)}),((t,n)=>{t.setTime(+t+n*Qg)}),((t,n)=>(n-t)/Qg),(t=>t.getUTCMinutes())),fy=cy.range,sy=Vg((t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*Kg-t.getMinutes()*Qg)}),((t,n)=>{t.setTime(+t+n*Jg)}),((t,n)=>(n-t)/Jg),(t=>t.getHours())),ly=sy.range,hy=Vg((t=>{t.setUTCMinutes(0,0,0)}),((t,n)=>{t.setTime(+t+n*Jg)}),((t,n)=>(n-t)/Jg),(t=>t.getUTCHours())),dy=hy.range,py=Vg((t=>t.setHours(0,0,0,0)),((t,n)=>t.setDate(t.getDate()+n)),((t,n)=>(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*Qg)/ty),(t=>t.getDate()-1)),gy=py.range,yy=Vg((t=>{t.setUTCHours(0,0,0,0)}),((t,n)=>{t.setUTCDate(t.getUTCDate()+n)}),((t,n)=>(n-t)/ty),(t=>t.getUTCDate()-1)),vy=yy.range,_y=Vg((t=>{t.setUTCHours(0,0,0,0)}),((t,n)=>{t.setUTCDate(t.getUTCDate()+n)}),((t,n)=>(n-t)/ty),(t=>Math.floor(t/ty))),by=_y.range;function my(t){return Vg((n=>{n.setDate(n.getDate()-(n.getDay()+7-t)%7),n.setHours(0,0,0,0)}),((t,n)=>{t.setDate(t.getDate()+7*n)}),((t,n)=>(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*Qg)/ny))}const xy=my(0),wy=my(1),My=my(2),Ty=my(3),Ay=my(4),Sy=my(5),Ey=my(6),Ny=xy.range,ky=wy.range,Cy=My.range,Py=Ty.range,zy=Ay.range,$y=Sy.range,Dy=Ey.range;function Ry(t){return Vg((n=>{n.setUTCDate(n.getUTCDate()-(n.getUTCDay()+7-t)%7),n.setUTCHours(0,0,0,0)}),((t,n)=>{t.setUTCDate(t.getUTCDate()+7*n)}),((t,n)=>(n-t)/ny))}const Fy=Ry(0),qy=Ry(1),Uy=Ry(2),Iy=Ry(3),Oy=Ry(4),By=Ry(5),Yy=Ry(6),Ly=Fy.range,jy=qy.range,Hy=Uy.range,Xy=Iy.range,Gy=Oy.range,Vy=By.range,Wy=Yy.range,Zy=Vg((t=>{t.setDate(1),t.setHours(0,0,0,0)}),((t,n)=>{t.setMonth(t.getMonth()+n)}),((t,n)=>n.getMonth()-t.getMonth()+12*(n.getFullYear()-t.getFullYear())),(t=>t.getMonth())),Ky=Zy.range,Qy=Vg((t=>{t.setUTCDate(1),t.setUTCHours(0,0,0,0)}),((t,n)=>{t.setUTCMonth(t.getUTCMonth()+n)}),((t,n)=>n.getUTCMonth()-t.getUTCMonth()+12*(n.getUTCFullYear()-t.getUTCFullYear())),(t=>t.getUTCMonth())),Jy=Qy.range,tv=Vg((t=>{t.setMonth(0,1),t.setHours(0,0,0,0)}),((t,n)=>{t.setFullYear(t.getFullYear()+n)}),((t,n)=>n.getFullYear()-t.getFullYear()),(t=>t.getFullYear()));tv.every=t=>isFinite(t=Math.floor(t))&&t>0?Vg((n=>{n.setFullYear(Math.floor(n.getFullYear()/t)*t),n.setMonth(0,1),n.setHours(0,0,0,0)}),((n,e)=>{n.setFullYear(n.getFullYear()+e*t)})):null;const nv=tv.range,ev=Vg((t=>{t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),((t,n)=>{t.setUTCFullYear(t.getUTCFullYear()+n)}),((t,n)=>n.getUTCFullYear()-t.getUTCFullYear()),(t=>t.getUTCFullYear()));ev.every=t=>isFinite(t=Math.floor(t))&&t>0?Vg((n=>{n.setUTCFullYear(Math.floor(n.getUTCFullYear()/t)*t),n.setUTCMonth(0,1),n.setUTCHours(0,0,0,0)}),((n,e)=>{n.setUTCFullYear(n.getUTCFullYear()+e*t)})):null;const rv=ev.range;function iv(t,n,e,i,o,a){const u=[[iy,1,Kg],[iy,5,5e3],[iy,15,15e3],[iy,30,3e4],[a,1,Qg],[a,5,3e5],[a,15,9e5],[a,30,18e5],[o,1,Jg],[o,3,108e5],[o,6,216e5],[o,12,432e5],[i,1,ty],[i,2,1728e5],[e,1,ny],[n,1,ey],[n,3,7776e6],[t,1,ry]];function c(n,e,i){const o=Math.abs(e-n)/i,a=r((([,,t])=>t)).right(u,o);if(a===u.length)return t.every(W(n/ry,e/ry,i));if(0===a)return Wg.every(Math.max(W(n,e,i),1));const[c,f]=u[o/u[a-1][2]=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:k_,s:C_,S:Zv,u:Kv,U:Qv,V:t_,w:n_,W:e_,x:null,X:null,y:r_,Y:o_,Z:u_,"%":N_},m={a:function(t){return a[t.getUTCDay()]},A:function(t){return o[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return u[t.getUTCMonth()]},c:null,d:c_,e:c_,f:d_,g:T_,G:S_,H:f_,I:s_,j:l_,L:h_,m:p_,M:g_,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:k_,s:C_,S:y_,u:v_,U:__,V:m_,w:x_,W:w_,x:null,X:null,y:M_,Y:A_,Z:E_,"%":N_},x={a:function(t,n,e){var r=d.exec(n.slice(e));return r?(t.w=p.get(r[0].toLowerCase()),e+r[0].length):-1},A:function(t,n,e){var r=l.exec(n.slice(e));return r?(t.w=h.get(r[0].toLowerCase()),e+r[0].length):-1},b:function(t,n,e){var r=v.exec(n.slice(e));return r?(t.m=_.get(r[0].toLowerCase()),e+r[0].length):-1},B:function(t,n,e){var r=g.exec(n.slice(e));return r?(t.m=y.get(r[0].toLowerCase()),e+r[0].length):-1},c:function(t,e,r){return T(t,n,e,r)},d:zv,e:zv,f:Uv,g:Nv,G:Ev,H:Dv,I:Dv,j:$v,L:qv,m:Pv,M:Rv,p:function(t,n,e){var r=f.exec(n.slice(e));return r?(t.p=s.get(r[0].toLowerCase()),e+r[0].length):-1},q:Cv,Q:Ov,s:Bv,S:Fv,u:Mv,U:Tv,V:Av,w:wv,W:Sv,x:function(t,n,r){return T(t,e,n,r)},X:function(t,n,e){return T(t,r,n,e)},y:Nv,Y:Ev,Z:kv,"%":Iv};function w(t,n){return function(e){var r,i,o,a=[],u=-1,c=0,f=t.length;for(e instanceof Date||(e=new Date(+e));++u53)return null;"w"in o||(o.w=1),"Z"in o?(i=(r=sv(lv(o.y,0,1))).getUTCDay(),r=i>4||0===i?qy.ceil(r):qy(r),r=yy.offset(r,7*(o.V-1)),o.y=r.getUTCFullYear(),o.m=r.getUTCMonth(),o.d=r.getUTCDate()+(o.w+6)%7):(i=(r=fv(lv(o.y,0,1))).getDay(),r=i>4||0===i?wy.ceil(r):wy(r),r=py.offset(r,7*(o.V-1)),o.y=r.getFullYear(),o.m=r.getMonth(),o.d=r.getDate()+(o.w+6)%7)}else("W"in o||"U"in o)&&("w"in o||(o.w="u"in o?o.u%7:"W"in o?1:0),i="Z"in o?sv(lv(o.y,0,1)).getUTCDay():fv(lv(o.y,0,1)).getDay(),o.m=0,o.d="W"in o?(o.w+6)%7+7*o.W-(i+5)%7:o.w+7*o.U-(i+6)%7);return"Z"in o?(o.H+=o.Z/100|0,o.M+=o.Z%100,sv(o)):fv(o)}}function T(t,n,e,r){for(var i,o,a=0,u=n.length,c=e.length;a=c)return-1;if(37===(i=n.charCodeAt(a++))){if(i=n.charAt(a++),!(o=x[i in pv?n.charAt(a++):i])||(r=o(t,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}return b.x=w(e,b),b.X=w(r,b),b.c=w(n,b),m.x=w(e,m),m.X=w(r,m),m.c=w(n,m),{format:function(t){var n=w(t+="",b);return n.toString=function(){return t},n},parse:function(t){var n=M(t+="",!1);return n.toString=function(){return t},n},utcFormat:function(t){var n=w(t+="",m);return n.toString=function(){return t},n},utcParse:function(t){var n=M(t+="",!0);return n.toString=function(){return t},n}}}var dv,pv={"-":"",_:" ",0:"0"},gv=/^\s*\d+/,yv=/^%/,vv=/[\\^$*+?|[\]().{}]/g;function _v(t,n,e){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o[t.toLowerCase(),n])))}function wv(t,n,e){var r=gv.exec(n.slice(e,e+1));return r?(t.w=+r[0],e+r[0].length):-1}function Mv(t,n,e){var r=gv.exec(n.slice(e,e+1));return r?(t.u=+r[0],e+r[0].length):-1}function Tv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.U=+r[0],e+r[0].length):-1}function Av(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.V=+r[0],e+r[0].length):-1}function Sv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.W=+r[0],e+r[0].length):-1}function Ev(t,n,e){var r=gv.exec(n.slice(e,e+4));return r?(t.y=+r[0],e+r[0].length):-1}function Nv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),e+r[0].length):-1}function kv(t,n,e){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(n.slice(e,e+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),e+r[0].length):-1}function Cv(t,n,e){var r=gv.exec(n.slice(e,e+1));return r?(t.q=3*r[0]-3,e+r[0].length):-1}function Pv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.m=r[0]-1,e+r[0].length):-1}function zv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.d=+r[0],e+r[0].length):-1}function $v(t,n,e){var r=gv.exec(n.slice(e,e+3));return r?(t.m=0,t.d=+r[0],e+r[0].length):-1}function Dv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.H=+r[0],e+r[0].length):-1}function Rv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.M=+r[0],e+r[0].length):-1}function Fv(t,n,e){var r=gv.exec(n.slice(e,e+2));return r?(t.S=+r[0],e+r[0].length):-1}function qv(t,n,e){var r=gv.exec(n.slice(e,e+3));return r?(t.L=+r[0],e+r[0].length):-1}function Uv(t,n,e){var r=gv.exec(n.slice(e,e+6));return r?(t.L=Math.floor(r[0]/1e3),e+r[0].length):-1}function Iv(t,n,e){var r=yv.exec(n.slice(e,e+1));return r?e+r[0].length:-1}function Ov(t,n,e){var r=gv.exec(n.slice(e));return r?(t.Q=+r[0],e+r[0].length):-1}function Bv(t,n,e){var r=gv.exec(n.slice(e));return r?(t.s=+r[0],e+r[0].length):-1}function Yv(t,n){return _v(t.getDate(),n,2)}function Lv(t,n){return _v(t.getHours(),n,2)}function jv(t,n){return _v(t.getHours()%12||12,n,2)}function Hv(t,n){return _v(1+py.count(tv(t),t),n,3)}function Xv(t,n){return _v(t.getMilliseconds(),n,3)}function Gv(t,n){return Xv(t,n)+"000"}function Vv(t,n){return _v(t.getMonth()+1,n,2)}function Wv(t,n){return _v(t.getMinutes(),n,2)}function Zv(t,n){return _v(t.getSeconds(),n,2)}function Kv(t){var n=t.getDay();return 0===n?7:n}function Qv(t,n){return _v(xy.count(tv(t)-1,t),n,2)}function Jv(t){var n=t.getDay();return n>=4||0===n?Ay(t):Ay.ceil(t)}function t_(t,n){return t=Jv(t),_v(Ay.count(tv(t),t)+(4===tv(t).getDay()),n,2)}function n_(t){return t.getDay()}function e_(t,n){return _v(wy.count(tv(t)-1,t),n,2)}function r_(t,n){return _v(t.getFullYear()%100,n,2)}function i_(t,n){return _v((t=Jv(t)).getFullYear()%100,n,2)}function o_(t,n){return _v(t.getFullYear()%1e4,n,4)}function a_(t,n){var e=t.getDay();return _v((t=e>=4||0===e?Ay(t):Ay.ceil(t)).getFullYear()%1e4,n,4)}function u_(t){var n=t.getTimezoneOffset();return(n>0?"-":(n*=-1,"+"))+_v(n/60|0,"0",2)+_v(n%60,"0",2)}function c_(t,n){return _v(t.getUTCDate(),n,2)}function f_(t,n){return _v(t.getUTCHours(),n,2)}function s_(t,n){return _v(t.getUTCHours()%12||12,n,2)}function l_(t,n){return _v(1+yy.count(ev(t),t),n,3)}function h_(t,n){return _v(t.getUTCMilliseconds(),n,3)}function d_(t,n){return h_(t,n)+"000"}function p_(t,n){return _v(t.getUTCMonth()+1,n,2)}function g_(t,n){return _v(t.getUTCMinutes(),n,2)}function y_(t,n){return _v(t.getUTCSeconds(),n,2)}function v_(t){var n=t.getUTCDay();return 0===n?7:n}function __(t,n){return _v(Fy.count(ev(t)-1,t),n,2)}function b_(t){var n=t.getUTCDay();return n>=4||0===n?Oy(t):Oy.ceil(t)}function m_(t,n){return t=b_(t),_v(Oy.count(ev(t),t)+(4===ev(t).getUTCDay()),n,2)}function x_(t){return t.getUTCDay()}function w_(t,n){return _v(qy.count(ev(t)-1,t),n,2)}function M_(t,n){return _v(t.getUTCFullYear()%100,n,2)}function T_(t,n){return _v((t=b_(t)).getUTCFullYear()%100,n,2)}function A_(t,n){return _v(t.getUTCFullYear()%1e4,n,4)}function S_(t,n){var e=t.getUTCDay();return _v((t=e>=4||0===e?Oy(t):Oy.ceil(t)).getUTCFullYear()%1e4,n,4)}function E_(){return"+0000"}function N_(){return"%"}function k_(t){return+t}function C_(t){return Math.floor(+t/1e3)}function P_(n){return dv=hv(n),t.timeFormat=dv.format,t.timeParse=dv.parse,t.utcFormat=dv.utcFormat,t.utcParse=dv.utcParse,dv}t.timeFormat=void 0,t.timeParse=void 0,t.utcFormat=void 0,t.utcParse=void 0,P_({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});var z_="%Y-%m-%dT%H:%M:%S.%LZ";var $_=Date.prototype.toISOString?function(t){return t.toISOString()}:t.utcFormat(z_),D_=$_;var R_=+new Date("2000-01-01T00:00:00.000Z")?function(t){var n=new Date(t);return isNaN(n)?null:n}:t.utcParse(z_),F_=R_;function q_(t){return new Date(t)}function U_(t){return t instanceof Date?+t:+new Date(+t)}function I_(t,n,e,r,i,o,a,u,c,f){var s=Sg(),l=s.invert,h=s.domain,d=f(".%L"),p=f(":%S"),g=f("%I:%M"),y=f("%I %p"),v=f("%a %d"),_=f("%b %d"),b=f("%B"),m=f("%Y");function x(t){return(c(t)Fr(t[t.length-1]),ib=new Array(3).concat("d8b365f5f5f55ab4ac","a6611adfc27d80cdc1018571","a6611adfc27df5f5f580cdc1018571","8c510ad8b365f6e8c3c7eae55ab4ac01665e","8c510ad8b365f6e8c3f5f5f5c7eae55ab4ac01665e","8c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e","8c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e","5430058c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e003c30","5430058c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e003c30").map(H_),ob=rb(ib),ab=new Array(3).concat("af8dc3f7f7f77fbf7b","7b3294c2a5cfa6dba0008837","7b3294c2a5cff7f7f7a6dba0008837","762a83af8dc3e7d4e8d9f0d37fbf7b1b7837","762a83af8dc3e7d4e8f7f7f7d9f0d37fbf7b1b7837","762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b7837","762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b7837","40004b762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b783700441b","40004b762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b783700441b").map(H_),ub=rb(ab),cb=new Array(3).concat("e9a3c9f7f7f7a1d76a","d01c8bf1b6dab8e1864dac26","d01c8bf1b6daf7f7f7b8e1864dac26","c51b7de9a3c9fde0efe6f5d0a1d76a4d9221","c51b7de9a3c9fde0eff7f7f7e6f5d0a1d76a4d9221","c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221","c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221","8e0152c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221276419","8e0152c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221276419").map(H_),fb=rb(cb),sb=new Array(3).concat("998ec3f7f7f7f1a340","5e3c99b2abd2fdb863e66101","5e3c99b2abd2f7f7f7fdb863e66101","542788998ec3d8daebfee0b6f1a340b35806","542788998ec3d8daebf7f7f7fee0b6f1a340b35806","5427888073acb2abd2d8daebfee0b6fdb863e08214b35806","5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b35806","2d004b5427888073acb2abd2d8daebfee0b6fdb863e08214b358067f3b08","2d004b5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b358067f3b08").map(H_),lb=rb(sb),hb=new Array(3).concat("ef8a62f7f7f767a9cf","ca0020f4a58292c5de0571b0","ca0020f4a582f7f7f792c5de0571b0","b2182bef8a62fddbc7d1e5f067a9cf2166ac","b2182bef8a62fddbc7f7f7f7d1e5f067a9cf2166ac","b2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac","b2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac","67001fb2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac053061","67001fb2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac053061").map(H_),db=rb(hb),pb=new Array(3).concat("ef8a62ffffff999999","ca0020f4a582bababa404040","ca0020f4a582ffffffbababa404040","b2182bef8a62fddbc7e0e0e09999994d4d4d","b2182bef8a62fddbc7ffffffe0e0e09999994d4d4d","b2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d","b2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d","67001fb2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d1a1a1a","67001fb2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d1a1a1a").map(H_),gb=rb(pb),yb=new Array(3).concat("fc8d59ffffbf91bfdb","d7191cfdae61abd9e92c7bb6","d7191cfdae61ffffbfabd9e92c7bb6","d73027fc8d59fee090e0f3f891bfdb4575b4","d73027fc8d59fee090ffffbfe0f3f891bfdb4575b4","d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4","d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4","a50026d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4313695","a50026d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4313695").map(H_),vb=rb(yb),_b=new Array(3).concat("fc8d59ffffbf91cf60","d7191cfdae61a6d96a1a9641","d7191cfdae61ffffbfa6d96a1a9641","d73027fc8d59fee08bd9ef8b91cf601a9850","d73027fc8d59fee08bffffbfd9ef8b91cf601a9850","d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850","d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850","a50026d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850006837","a50026d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850006837").map(H_),bb=rb(_b),mb=new Array(3).concat("fc8d59ffffbf99d594","d7191cfdae61abdda42b83ba","d7191cfdae61ffffbfabdda42b83ba","d53e4ffc8d59fee08be6f59899d5943288bd","d53e4ffc8d59fee08bffffbfe6f59899d5943288bd","d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd","d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd","9e0142d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd5e4fa2","9e0142d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd5e4fa2").map(H_),xb=rb(mb),wb=new Array(3).concat("e5f5f999d8c92ca25f","edf8fbb2e2e266c2a4238b45","edf8fbb2e2e266c2a42ca25f006d2c","edf8fbccece699d8c966c2a42ca25f006d2c","edf8fbccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45006d2c00441b").map(H_),Mb=rb(wb),Tb=new Array(3).concat("e0ecf49ebcda8856a7","edf8fbb3cde38c96c688419d","edf8fbb3cde38c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d810f7c4d004b").map(H_),Ab=rb(Tb),Sb=new Array(3).concat("e0f3dba8ddb543a2ca","f0f9e8bae4bc7bccc42b8cbe","f0f9e8bae4bc7bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe0868ac084081").map(H_),Eb=rb(Sb),Nb=new Array(3).concat("fee8c8fdbb84e34a33","fef0d9fdcc8afc8d59d7301f","fef0d9fdcc8afc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301fb300007f0000").map(H_),kb=rb(Nb),Cb=new Array(3).concat("ece2f0a6bddb1c9099","f6eff7bdc9e167a9cf02818a","f6eff7bdc9e167a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016c59014636").map(H_),Pb=rb(Cb),zb=new Array(3).concat("ece7f2a6bddb2b8cbe","f1eef6bdc9e174a9cf0570b0","f1eef6bdc9e174a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0045a8d023858").map(H_),$b=rb(zb),Db=new Array(3).concat("e7e1efc994c7dd1c77","f1eef6d7b5d8df65b0ce1256","f1eef6d7b5d8df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125698004367001f").map(H_),Rb=rb(Db),Fb=new Array(3).concat("fde0ddfa9fb5c51b8a","feebe2fbb4b9f768a1ae017e","feebe2fbb4b9f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a017749006a").map(H_),qb=rb(Fb),Ub=new Array(3).concat("edf8b17fcdbb2c7fb8","ffffcca1dab441b6c4225ea8","ffffcca1dab441b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea8253494081d58").map(H_),Ib=rb(Ub),Ob=new Array(3).concat("f7fcb9addd8e31a354","ffffccc2e69978c679238443","ffffccc2e69978c67931a354006837","ffffccd9f0a3addd8e78c67931a354006837","ffffccd9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443006837004529").map(H_),Bb=rb(Ob),Yb=new Array(3).concat("fff7bcfec44fd95f0e","ffffd4fed98efe9929cc4c02","ffffd4fed98efe9929d95f0e993404","ffffd4fee391fec44ffe9929d95f0e993404","ffffd4fee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c02993404662506").map(H_),Lb=rb(Yb),jb=new Array(3).concat("ffeda0feb24cf03b20","ffffb2fecc5cfd8d3ce31a1c","ffffb2fecc5cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cbd0026800026").map(H_),Hb=rb(jb),Xb=new Array(3).concat("deebf79ecae13182bd","eff3ffbdd7e76baed62171b5","eff3ffbdd7e76baed63182bd08519c","eff3ffc6dbef9ecae16baed63182bd08519c","eff3ffc6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b508519c08306b").map(H_),Gb=rb(Xb),Vb=new Array(3).concat("e5f5e0a1d99b31a354","edf8e9bae4b374c476238b45","edf8e9bae4b374c47631a354006d2c","edf8e9c7e9c0a1d99b74c47631a354006d2c","edf8e9c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45006d2c00441b").map(H_),Wb=rb(Vb),Zb=new Array(3).concat("f0f0f0bdbdbd636363","f7f7f7cccccc969696525252","f7f7f7cccccc969696636363252525","f7f7f7d9d9d9bdbdbd969696636363252525","f7f7f7d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525000000").map(H_),Kb=rb(Zb),Qb=new Array(3).concat("efedf5bcbddc756bb1","f2f0f7cbc9e29e9ac86a51a3","f2f0f7cbc9e29e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a354278f3f007d").map(H_),Jb=rb(Qb),tm=new Array(3).concat("fee0d2fc9272de2d26","fee5d9fcae91fb6a4acb181d","fee5d9fcae91fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181da50f1567000d").map(H_),nm=rb(tm),em=new Array(3).concat("fee6cefdae6be6550d","feeddefdbe85fd8d3cd94701","feeddefdbe85fd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d94801a636037f2704").map(H_),rm=rb(em);var im=hi(Tr(300,.5,0),Tr(-240,.5,1)),om=hi(Tr(-100,.75,.35),Tr(80,1.5,.8)),am=hi(Tr(260,.75,.35),Tr(80,1.5,.8)),um=Tr();var cm=Fe(),fm=Math.PI/3,sm=2*Math.PI/3;function lm(t){var n=t.length;return function(e){return t[Math.max(0,Math.min(n-1,Math.floor(e*n)))]}}var hm=lm(H_("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")),dm=lm(H_("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),pm=lm(H_("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),gm=lm(H_("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));function ym(t){return function(){return t}}const vm=Math.abs,_m=Math.atan2,bm=Math.cos,mm=Math.max,xm=Math.min,wm=Math.sin,Mm=Math.sqrt,Tm=1e-12,Am=Math.PI,Sm=Am/2,Em=2*Am;function Nm(t){return t>=1?Sm:t<=-1?-Sm:Math.asin(t)}function km(t){let n=3;return t.digits=function(e){if(!arguments.length)return n;if(null==e)n=null;else{const t=Math.floor(e);if(!(t>=0))throw new RangeError(`invalid digits: ${e}`);n=t}return t},()=>new Ua(n)}function Cm(t){return t.innerRadius}function Pm(t){return t.outerRadius}function zm(t){return t.startAngle}function $m(t){return t.endAngle}function Dm(t){return t&&t.padAngle}function Rm(t,n,e,r,i,o,a){var u=t-e,c=n-r,f=(a?o:-o)/Mm(u*u+c*c),s=f*c,l=-f*u,h=t+s,d=n+l,p=e+s,g=r+l,y=(h+p)/2,v=(d+g)/2,_=p-h,b=g-d,m=_*_+b*b,x=i-o,w=h*g-p*d,M=(b<0?-1:1)*Mm(mm(0,x*x*m-w*w)),T=(w*b-_*M)/m,A=(-w*_-b*M)/m,S=(w*b+_*M)/m,E=(-w*_+b*M)/m,N=T-y,k=A-v,C=S-y,P=E-v;return N*N+k*k>C*C+P*P&&(T=S,A=E),{cx:T,cy:A,x01:-s,y01:-l,x11:T*(i/x-1),y11:A*(i/x-1)}}var Fm=Array.prototype.slice;function qm(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}function Um(t){this._context=t}function Im(t){return new Um(t)}function Om(t){return t[0]}function Bm(t){return t[1]}function Ym(t,n){var e=ym(!0),r=null,i=Im,o=null,a=km(u);function u(u){var c,f,s,l=(u=qm(u)).length,h=!1;for(null==r&&(o=i(s=a())),c=0;c<=l;++c)!(c=l;--h)u.point(v[h],_[h]);u.lineEnd(),u.areaEnd()}y&&(v[s]=+t(d,s,f),_[s]=+n(d,s,f),u.point(r?+r(d,s,f):v[s],e?+e(d,s,f):_[s]))}if(p)return u=null,p+""||null}function s(){return Ym().defined(i).curve(a).context(o)}return t="function"==typeof t?t:void 0===t?Om:ym(+t),n="function"==typeof n?n:ym(void 0===n?0:+n),e="function"==typeof e?e:void 0===e?Bm:ym(+e),f.x=function(n){return arguments.length?(t="function"==typeof n?n:ym(+n),r=null,f):t},f.x0=function(n){return arguments.length?(t="function"==typeof n?n:ym(+n),f):t},f.x1=function(t){return arguments.length?(r=null==t?null:"function"==typeof t?t:ym(+t),f):r},f.y=function(t){return arguments.length?(n="function"==typeof t?t:ym(+t),e=null,f):n},f.y0=function(t){return arguments.length?(n="function"==typeof t?t:ym(+t),f):n},f.y1=function(t){return arguments.length?(e=null==t?null:"function"==typeof t?t:ym(+t),f):e},f.lineX0=f.lineY0=function(){return s().x(t).y(n)},f.lineY1=function(){return s().x(t).y(e)},f.lineX1=function(){return s().x(r).y(n)},f.defined=function(t){return arguments.length?(i="function"==typeof t?t:ym(!!t),f):i},f.curve=function(t){return arguments.length?(a=t,null!=o&&(u=a(o)),f):a},f.context=function(t){return arguments.length?(null==t?o=u=null:u=a(o=t),f):o},f}function jm(t,n){return nt?1:n>=t?0:NaN}function Hm(t){return t}Um.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:this._context.lineTo(t,n)}}};var Xm=Vm(Im);function Gm(t){this._curve=t}function Vm(t){function n(n){return new Gm(t(n))}return n._curve=t,n}function Wm(t){var n=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t.curve=function(t){return arguments.length?n(Vm(t)):n()._curve},t}function Zm(){return Wm(Ym().curve(Xm))}function Km(){var t=Lm().curve(Xm),n=t.curve,e=t.lineX0,r=t.lineX1,i=t.lineY0,o=t.lineY1;return t.angle=t.x,delete t.x,t.startAngle=t.x0,delete t.x0,t.endAngle=t.x1,delete t.x1,t.radius=t.y,delete t.y,t.innerRadius=t.y0,delete t.y0,t.outerRadius=t.y1,delete t.y1,t.lineStartAngle=function(){return Wm(e())},delete t.lineX0,t.lineEndAngle=function(){return Wm(r())},delete t.lineX1,t.lineInnerRadius=function(){return Wm(i())},delete t.lineY0,t.lineOuterRadius=function(){return Wm(o())},delete t.lineY1,t.curve=function(t){return arguments.length?n(Vm(t)):n()._curve},t}function Qm(t,n){return[(n=+n)*Math.cos(t-=Math.PI/2),n*Math.sin(t)]}Gm.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},lineEnd:function(){this._curve.lineEnd()},point:function(t,n){this._curve.point(n*Math.sin(t),n*-Math.cos(t))}};class Jm{constructor(t,n){this._context=t,this._x=n}areaStart(){this._line=0}areaEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line}point(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:this._x?this._context.bezierCurveTo(this._x0=(this._x0+t)/2,this._y0,this._x0,n,t,n):this._context.bezierCurveTo(this._x0,this._y0=(this._y0+n)/2,t,this._y0,t,n)}this._x0=t,this._y0=n}}class tx{constructor(t){this._context=t}lineStart(){this._point=0}lineEnd(){}point(t,n){if(t=+t,n=+n,0===this._point)this._point=1;else{const e=Qm(this._x0,this._y0),r=Qm(this._x0,this._y0=(this._y0+n)/2),i=Qm(t,this._y0),o=Qm(t,n);this._context.moveTo(...e),this._context.bezierCurveTo(...r,...i,...o)}this._x0=t,this._y0=n}}function nx(t){return new Jm(t,!0)}function ex(t){return new Jm(t,!1)}function rx(t){return new tx(t)}function ix(t){return t.source}function ox(t){return t.target}function ax(t){let n=ix,e=ox,r=Om,i=Bm,o=null,a=null,u=km(c);function c(){let c;const f=Fm.call(arguments),s=n.apply(this,f),l=e.apply(this,f);if(null==o&&(a=t(c=u())),a.lineStart(),f[0]=s,a.point(+r.apply(this,f),+i.apply(this,f)),f[0]=l,a.point(+r.apply(this,f),+i.apply(this,f)),a.lineEnd(),c)return a=null,c+""||null}return c.source=function(t){return arguments.length?(n=t,c):n},c.target=function(t){return arguments.length?(e=t,c):e},c.x=function(t){return arguments.length?(r="function"==typeof t?t:ym(+t),c):r},c.y=function(t){return arguments.length?(i="function"==typeof t?t:ym(+t),c):i},c.context=function(n){return arguments.length?(null==n?o=a=null:a=t(o=n),c):o},c}const ux=Mm(3);var cx={draw(t,n){const e=.59436*Mm(n+xm(n/28,.75)),r=e/2,i=r*ux;t.moveTo(0,e),t.lineTo(0,-e),t.moveTo(-i,-r),t.lineTo(i,r),t.moveTo(-i,r),t.lineTo(i,-r)}},fx={draw(t,n){const e=Mm(n/Am);t.moveTo(e,0),t.arc(0,0,e,0,Em)}},sx={draw(t,n){const e=Mm(n/5)/2;t.moveTo(-3*e,-e),t.lineTo(-e,-e),t.lineTo(-e,-3*e),t.lineTo(e,-3*e),t.lineTo(e,-e),t.lineTo(3*e,-e),t.lineTo(3*e,e),t.lineTo(e,e),t.lineTo(e,3*e),t.lineTo(-e,3*e),t.lineTo(-e,e),t.lineTo(-3*e,e),t.closePath()}};const lx=Mm(1/3),hx=2*lx;var dx={draw(t,n){const e=Mm(n/hx),r=e*lx;t.moveTo(0,-e),t.lineTo(r,0),t.lineTo(0,e),t.lineTo(-r,0),t.closePath()}},px={draw(t,n){const e=.62625*Mm(n);t.moveTo(0,-e),t.lineTo(e,0),t.lineTo(0,e),t.lineTo(-e,0),t.closePath()}},gx={draw(t,n){const e=.87559*Mm(n-xm(n/7,2));t.moveTo(-e,0),t.lineTo(e,0),t.moveTo(0,e),t.lineTo(0,-e)}},yx={draw(t,n){const e=Mm(n),r=-e/2;t.rect(r,r,e,e)}},vx={draw(t,n){const e=.4431*Mm(n);t.moveTo(e,e),t.lineTo(e,-e),t.lineTo(-e,-e),t.lineTo(-e,e),t.closePath()}};const _x=wm(Am/10)/wm(7*Am/10),bx=wm(Em/10)*_x,mx=-bm(Em/10)*_x;var xx={draw(t,n){const e=Mm(.8908130915292852*n),r=bx*e,i=mx*e;t.moveTo(0,-e),t.lineTo(r,i);for(let n=1;n<5;++n){const o=Em*n/5,a=bm(o),u=wm(o);t.lineTo(u*e,-a*e),t.lineTo(a*r-u*i,u*r+a*i)}t.closePath()}};const wx=Mm(3);var Mx={draw(t,n){const e=-Mm(n/(3*wx));t.moveTo(0,2*e),t.lineTo(-wx*e,-e),t.lineTo(wx*e,-e),t.closePath()}};const Tx=Mm(3);var Ax={draw(t,n){const e=.6824*Mm(n),r=e/2,i=e*Tx/2;t.moveTo(0,-e),t.lineTo(i,r),t.lineTo(-i,r),t.closePath()}};const Sx=-.5,Ex=Mm(3)/2,Nx=1/Mm(12),kx=3*(Nx/2+1);var Cx={draw(t,n){const e=Mm(n/kx),r=e/2,i=e*Nx,o=r,a=e*Nx+e,u=-o,c=a;t.moveTo(r,i),t.lineTo(o,a),t.lineTo(u,c),t.lineTo(Sx*r-Ex*i,Ex*r+Sx*i),t.lineTo(Sx*o-Ex*a,Ex*o+Sx*a),t.lineTo(Sx*u-Ex*c,Ex*u+Sx*c),t.lineTo(Sx*r+Ex*i,Sx*i-Ex*r),t.lineTo(Sx*o+Ex*a,Sx*a-Ex*o),t.lineTo(Sx*u+Ex*c,Sx*c-Ex*u),t.closePath()}},Px={draw(t,n){const e=.6189*Mm(n-xm(n/6,1.7));t.moveTo(-e,-e),t.lineTo(e,e),t.moveTo(-e,e),t.lineTo(e,-e)}};const zx=[fx,sx,dx,yx,xx,Mx,Cx],$x=[fx,gx,Px,Ax,cx,vx,px];function Dx(){}function Rx(t,n,e){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+n)/6,(t._y0+4*t._y1+e)/6)}function Fx(t){this._context=t}function qx(t){this._context=t}function Ux(t){this._context=t}function Ix(t,n){this._basis=new Fx(t),this._beta=n}Fx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:Rx(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:Rx(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},qx.prototype={areaStart:Dx,areaEnd:Dx,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x2=t,this._y2=n;break;case 1:this._point=2,this._x3=t,this._y3=n;break;case 2:this._point=3,this._x4=t,this._y4=n,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+n)/6);break;default:Rx(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},Ux.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var e=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+n)/6;this._line?this._context.lineTo(e,r):this._context.moveTo(e,r);break;case 3:this._point=4;default:Rx(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},Ix.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,n=this._y,e=t.length-1;if(e>0)for(var r,i=t[0],o=n[0],a=t[e]-i,u=n[e]-o,c=-1;++c<=e;)r=c/e,this._basis.point(this._beta*t[c]+(1-this._beta)*(i+r*a),this._beta*n[c]+(1-this._beta)*(o+r*u));this._x=this._y=null,this._basis.lineEnd()},point:function(t,n){this._x.push(+t),this._y.push(+n)}};var Ox=function t(n){function e(t){return 1===n?new Fx(t):new Ix(t,n)}return e.beta=function(n){return t(+n)},e}(.85);function Bx(t,n,e){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-n),t._y2+t._k*(t._y1-e),t._x2,t._y2)}function Yx(t,n){this._context=t,this._k=(1-n)/6}Yx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:Bx(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2,this._x1=t,this._y1=n;break;case 2:this._point=3;default:Bx(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Lx=function t(n){function e(t){return new Yx(t,n)}return e.tension=function(n){return t(+n)},e}(0);function jx(t,n){this._context=t,this._k=(1-n)/6}jx.prototype={areaStart:Dx,areaEnd:Dx,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:Bx(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Hx=function t(n){function e(t){return new jx(t,n)}return e.tension=function(n){return t(+n)},e}(0);function Xx(t,n){this._context=t,this._k=(1-n)/6}Xx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:Bx(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Gx=function t(n){function e(t){return new Xx(t,n)}return e.tension=function(n){return t(+n)},e}(0);function Vx(t,n,e){var r=t._x1,i=t._y1,o=t._x2,a=t._y2;if(t._l01_a>Tm){var u=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,c=3*t._l01_a*(t._l01_a+t._l12_a);r=(r*u-t._x0*t._l12_2a+t._x2*t._l01_2a)/c,i=(i*u-t._y0*t._l12_2a+t._y2*t._l01_2a)/c}if(t._l23_a>Tm){var f=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,s=3*t._l23_a*(t._l23_a+t._l12_a);o=(o*f+t._x1*t._l23_2a-n*t._l12_2a)/s,a=(a*f+t._y1*t._l23_2a-e*t._l12_2a)/s}t._context.bezierCurveTo(r,i,o,a,t._x2,t._y2)}function Wx(t,n){this._context=t,this._alpha=n}Wx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3;default:Vx(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Zx=function t(n){function e(t){return n?new Wx(t,n):new Yx(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);function Kx(t,n){this._context=t,this._alpha=n}Kx.prototype={areaStart:Dx,areaEnd:Dx,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:Vx(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Qx=function t(n){function e(t){return n?new Kx(t,n):new jx(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);function Jx(t,n){this._context=t,this._alpha=n}Jx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:Vx(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var tw=function t(n){function e(t){return n?new Jx(t,n):new Xx(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);function nw(t){this._context=t}function ew(t){return t<0?-1:1}function rw(t,n,e){var r=t._x1-t._x0,i=n-t._x1,o=(t._y1-t._y0)/(r||i<0&&-0),a=(e-t._y1)/(i||r<0&&-0),u=(o*i+a*r)/(r+i);return(ew(o)+ew(a))*Math.min(Math.abs(o),Math.abs(a),.5*Math.abs(u))||0}function iw(t,n){var e=t._x1-t._x0;return e?(3*(t._y1-t._y0)/e-n)/2:n}function ow(t,n,e){var r=t._x0,i=t._y0,o=t._x1,a=t._y1,u=(o-r)/3;t._context.bezierCurveTo(r+u,i+u*n,o-u,a-u*e,o,a)}function aw(t){this._context=t}function uw(t){this._context=new cw(t)}function cw(t){this._context=t}function fw(t){this._context=t}function sw(t){var n,e,r=t.length-1,i=new Array(r),o=new Array(r),a=new Array(r);for(i[0]=0,o[0]=2,a[0]=t[0]+2*t[1],n=1;n=0;--n)i[n]=(a[n]-i[n+1])/o[n];for(o[r-1]=(t[r]+i[r-1])/2,n=0;n1)for(var e,r,i,o=1,a=t[n[0]],u=a.length;o=0;)e[n]=n;return e}function pw(t,n){return t[n]}function gw(t){const n=[];return n.key=t,n}function yw(t){var n=t.map(vw);return dw(t).sort((function(t,e){return n[t]-n[e]}))}function vw(t){for(var n,e=-1,r=0,i=t.length,o=-1/0;++eo&&(o=n,r=e);return r}function _w(t){var n=t.map(bw);return dw(t).sort((function(t,e){return n[t]-n[e]}))}function bw(t){for(var n,e=0,r=-1,i=t.length;++r=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,n),this._context.lineTo(t,n);else{var e=this._x*(1-this._t)+t*this._t;this._context.lineTo(e,this._y),this._context.lineTo(e,n)}}this._x=t,this._y=n}};var mw=t=>()=>t;function xw(t,{sourceEvent:n,target:e,transform:r,dispatch:i}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:n,enumerable:!0,configurable:!0},target:{value:e,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:i}})}function ww(t,n,e){this.k=t,this.x=n,this.y=e}ww.prototype={constructor:ww,scale:function(t){return 1===t?this:new ww(this.k*t,this.x,this.y)},translate:function(t,n){return 0===t&0===n?this:new ww(this.k,this.x+this.k*t,this.y+this.k*n)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Mw=new ww(1,0,0);function Tw(t){for(;!t.__zoom;)if(!(t=t.parentNode))return Mw;return t.__zoom}function Aw(t){t.stopImmediatePropagation()}function Sw(t){t.preventDefault(),t.stopImmediatePropagation()}function Ew(t){return!(t.ctrlKey&&"wheel"!==t.type||t.button)}function Nw(){var t=this;return t instanceof SVGElement?(t=t.ownerSVGElement||t).hasAttribute("viewBox")?[[(t=t.viewBox.baseVal).x,t.y],[t.x+t.width,t.y+t.height]]:[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]:[[0,0],[t.clientWidth,t.clientHeight]]}function kw(){return this.__zoom||Mw}function Cw(t){return-t.deltaY*(1===t.deltaMode?.05:t.deltaMode?1:.002)*(t.ctrlKey?10:1)}function Pw(){return navigator.maxTouchPoints||"ontouchstart"in this}function zw(t,n,e){var r=t.invertX(n[0][0])-e[0][0],i=t.invertX(n[1][0])-e[1][0],o=t.invertY(n[0][1])-e[0][1],a=t.invertY(n[1][1])-e[1][1];return t.translate(i>r?(r+i)/2:Math.min(0,r)||Math.max(0,i),a>o?(o+a)/2:Math.min(0,o)||Math.max(0,a))}Tw.prototype=ww.prototype,t.Adder=T,t.Delaunay=Lu,t.FormatSpecifier=tf,t.InternMap=InternMap,t.InternSet=InternSet,t.Node=Qd,t.Path=Ua,t.Voronoi=qu,t.ZoomTransform=ww,t.active=function(t,n){var e,r,i=t.__transition;if(i)for(r in n=null==n?null:n+"",i)if((e=i[r]).state>qi&&e.name===n)return new po([[t]],Zo,n,+r);return null},t.arc=function(){var t=Cm,n=Pm,e=ym(0),r=null,i=zm,o=$m,a=Dm,u=null,c=km(f);function f(){var f,s,l=+t.apply(this,arguments),h=+n.apply(this,arguments),d=i.apply(this,arguments)-Sm,p=o.apply(this,arguments)-Sm,g=vm(p-d),y=p>d;if(u||(u=f=c()),hTm)if(g>Em-Tm)u.moveTo(h*bm(d),h*wm(d)),u.arc(0,0,h,d,p,!y),l>Tm&&(u.moveTo(l*bm(p),l*wm(p)),u.arc(0,0,l,p,d,y));else{var v,_,b=d,m=p,x=d,w=p,M=g,T=g,A=a.apply(this,arguments)/2,S=A>Tm&&(r?+r.apply(this,arguments):Mm(l*l+h*h)),E=xm(vm(h-l)/2,+e.apply(this,arguments)),N=E,k=E;if(S>Tm){var C=Nm(S/l*wm(A)),P=Nm(S/h*wm(A));(M-=2*C)>Tm?(x+=C*=y?1:-1,w-=C):(M=0,x=w=(d+p)/2),(T-=2*P)>Tm?(b+=P*=y?1:-1,m-=P):(T=0,b=m=(d+p)/2)}var z=h*bm(b),$=h*wm(b),D=l*bm(w),R=l*wm(w);if(E>Tm){var F,q=h*bm(m),U=h*wm(m),I=l*bm(x),O=l*wm(x);if(g1?0:t<-1?Am:Math.acos(t)}((B*L+Y*j)/(Mm(B*B+Y*Y)*Mm(L*L+j*j)))/2),X=Mm(F[0]*F[0]+F[1]*F[1]);N=xm(E,(l-X)/(H-1)),k=xm(E,(h-X)/(H+1))}else N=k=0}T>Tm?k>Tm?(v=Rm(I,O,z,$,h,k,y),_=Rm(q,U,D,R,h,k,y),u.moveTo(v.cx+v.x01,v.cy+v.y01),kTm&&M>Tm?N>Tm?(v=Rm(D,R,q,U,l,-N,y),_=Rm(z,$,I,O,l,-N,y),u.lineTo(v.cx+v.x01,v.cy+v.y01),N=0))throw new RangeError("invalid r");let e=t.length;if(!((e=Math.floor(e))>=0))throw new RangeError("invalid length");if(!e||!n)return t;const r=y(n),i=t.slice();return r(t,i,0,e,1),r(i,t,0,e,1),r(t,i,0,e,1),t},t.blur2=l,t.blurImage=h,t.brush=function(){return wa(la)},t.brushSelection=function(t){var n=t.__brush;return n?n.dim.output(n.selection):null},t.brushX=function(){return wa(fa)},t.brushY=function(){return wa(sa)},t.buffer=function(t,n){return fetch(t,n).then(_c)},t.chord=function(){return za(!1,!1)},t.chordDirected=function(){return za(!0,!1)},t.chordTranspose=function(){return za(!1,!0)},t.cluster=function(){var t=Ld,n=1,e=1,r=!1;function i(i){var o,a=0;i.eachAfter((function(n){var e=n.children;e?(n.x=function(t){return t.reduce(jd,0)/t.length}(e),n.y=function(t){return 1+t.reduce(Hd,0)}(e)):(n.x=o?a+=t(n,o):0,n.y=0,o=n)}));var u=function(t){for(var n;n=t.children;)t=n[0];return t}(i),c=function(t){for(var n;n=t.children;)t=n[n.length-1];return t}(i),f=u.x-t(u,c)/2,s=c.x+t(c,u)/2;return i.eachAfter(r?function(t){t.x=(t.x-i.x)*n,t.y=(i.y-t.y)*e}:function(t){t.x=(t.x-f)/(s-f)*n,t.y=(1-(i.y?t.y/i.y:1))*e})}return i.separation=function(n){return arguments.length?(t=n,i):t},i.size=function(t){return arguments.length?(r=!1,n=+t[0],e=+t[1],i):r?null:[n,e]},i.nodeSize=function(t){return arguments.length?(r=!0,n=+t[0],e=+t[1],i):r?[n,e]:null},i},t.color=ze,t.contourDensity=function(){var t=fu,n=su,e=lu,r=960,i=500,o=20,a=2,u=3*o,c=r+2*u>>a,f=i+2*u>>a,s=Qa(20);function h(r){var i=new Float32Array(c*f),s=Math.pow(2,-a),h=-1;for(const o of r){var d=(t(o,++h,r)+u)*s,p=(n(o,h,r)+u)*s,g=+e(o,h,r);if(g&&d>=0&&d=0&&pt*r)))(n).map(((t,n)=>(t.value=+e[n],p(t))))}function p(t){return t.coordinates.forEach(g),t}function g(t){t.forEach(y)}function y(t){t.forEach(v)}function v(t){t[0]=t[0]*Math.pow(2,a)-u,t[1]=t[1]*Math.pow(2,a)-u}function _(){return c=r+2*(u=3*o)>>a,f=i+2*u>>a,d}return d.contours=function(t){var n=h(t),e=iu().size([c,f]),r=Math.pow(2,2*a),i=t=>{t=+t;var i=p(e.contour(n,t*r));return i.value=t,i};return Object.defineProperty(i,"max",{get:()=>J(n)/r}),i},d.x=function(n){return arguments.length?(t="function"==typeof n?n:Qa(+n),d):t},d.y=function(t){return arguments.length?(n="function"==typeof t?t:Qa(+t),d):n},d.weight=function(t){return arguments.length?(e="function"==typeof t?t:Qa(+t),d):e},d.size=function(t){if(!arguments.length)return[r,i];var n=+t[0],e=+t[1];if(!(n>=0&&e>=0))throw new Error("invalid size");return r=n,i=e,_()},d.cellSize=function(t){if(!arguments.length)return 1<=1))throw new Error("invalid cell size");return a=Math.floor(Math.log(t)/Math.LN2),_()},d.thresholds=function(t){return arguments.length?(s="function"==typeof t?t:Array.isArray(t)?Qa(Za.call(t)):Qa(t),d):s},d.bandwidth=function(t){if(!arguments.length)return Math.sqrt(o*(o+1));if(!((t=+t)>=0))throw new Error("invalid bandwidth");return o=(Math.sqrt(4*t*t+1)-1)/2,_()},d},t.contours=iu,t.count=v,t.create=function(t){return Zn(Yt(t).call(document.documentElement))},t.creator=Yt,t.cross=function(...t){const n="function"==typeof t[t.length-1]&&function(t){return n=>t(...n)}(t.pop()),e=(t=t.map(m)).map(_),r=t.length-1,i=new Array(r+1).fill(0),o=[];if(r<0||e.some(b))return o;for(;;){o.push(i.map(((n,e)=>t[e][n])));let a=r;for(;++i[a]===e[a];){if(0===a)return n?o.map(n):o;i[a--]=0}}},t.csv=wc,t.csvFormat=rc,t.csvFormatBody=ic,t.csvFormatRow=ac,t.csvFormatRows=oc,t.csvFormatValue=uc,t.csvParse=nc,t.csvParseRows=ec,t.cubehelix=Tr,t.cumsum=function(t,n){var e=0,r=0;return Float64Array.from(t,void 0===n?t=>e+=+t||0:i=>e+=+n(i,r++,t)||0)},t.curveBasis=function(t){return new Fx(t)},t.curveBasisClosed=function(t){return new qx(t)},t.curveBasisOpen=function(t){return new Ux(t)},t.curveBumpX=nx,t.curveBumpY=ex,t.curveBundle=Ox,t.curveCardinal=Lx,t.curveCardinalClosed=Hx,t.curveCardinalOpen=Gx,t.curveCatmullRom=Zx,t.curveCatmullRomClosed=Qx,t.curveCatmullRomOpen=tw,t.curveLinear=Im,t.curveLinearClosed=function(t){return new nw(t)},t.curveMonotoneX=function(t){return new aw(t)},t.curveMonotoneY=function(t){return new uw(t)},t.curveNatural=function(t){return new fw(t)},t.curveStep=function(t){return new lw(t,.5)},t.curveStepAfter=function(t){return new lw(t,1)},t.curveStepBefore=function(t){return new lw(t,0)},t.descending=e,t.deviation=w,t.difference=function(t,...n){t=new InternSet(t);for(const e of n)for(const n of e)t.delete(n);return t},t.disjoint=function(t,n){const e=n[Symbol.iterator](),r=new InternSet;for(const n of t){if(r.has(n))return!1;let t,i;for(;({value:t,done:i}=e.next())&&!i;){if(Object.is(n,t))return!1;r.add(t)}}return!0},t.dispatch=$t,t.drag=function(){var t,n,e,r,i=se,o=le,a=he,u=de,c={},f=$t("start","drag","end"),s=0,l=0;function h(t){t.on("mousedown.drag",d).filter(u).on("touchstart.drag",y).on("touchmove.drag",v,ee).on("touchend.drag touchcancel.drag",_).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function d(a,u){if(!r&&i.call(this,a,u)){var c=b(this,o.call(this,a,u),a,u,"mouse");c&&(Zn(a.view).on("mousemove.drag",p,re).on("mouseup.drag",g,re),ae(a.view),ie(a),e=!1,t=a.clientX,n=a.clientY,c("start",a))}}function p(r){if(oe(r),!e){var i=r.clientX-t,o=r.clientY-n;e=i*i+o*o>l}c.mouse("drag",r)}function g(t){Zn(t.view).on("mousemove.drag mouseup.drag",null),ue(t.view,e),oe(t),c.mouse("end",t)}function y(t,n){if(i.call(this,t,n)){var e,r,a=t.changedTouches,u=o.call(this,t,n),c=a.length;for(e=0;e+t,t.easePoly=wo,t.easePolyIn=mo,t.easePolyInOut=wo,t.easePolyOut=xo,t.easeQuad=_o,t.easeQuadIn=function(t){return t*t},t.easeQuadInOut=_o,t.easeQuadOut=function(t){return t*(2-t)},t.easeSin=Ao,t.easeSinIn=function(t){return 1==+t?1:1-Math.cos(t*To)},t.easeSinInOut=Ao,t.easeSinOut=function(t){return Math.sin(t*To)},t.every=function(t,n){if("function"!=typeof n)throw new TypeError("test is not a function");let e=-1;for(const r of t)if(!n(r,++e,t))return!1;return!0},t.extent=M,t.fcumsum=function(t,n){const e=new T;let r=-1;return Float64Array.from(t,void 0===n?t=>e.add(+t||0):i=>e.add(+n(i,++r,t)||0))},t.filter=function(t,n){if("function"!=typeof n)throw new TypeError("test is not a function");const e=[];let r=-1;for(const i of t)n(i,++r,t)&&e.push(i);return e},t.flatGroup=function(t,...n){return z(P(t,...n),n)},t.flatRollup=function(t,n,...e){return z(D(t,n,...e),e)},t.forceCenter=function(t,n){var e,r=1;function i(){var i,o,a=e.length,u=0,c=0;for(i=0;if+p||os+p||ac.index){var g=f-u.x-u.vx,y=s-u.y-u.vy,v=g*g+y*y;vt.r&&(t.r=t[n].r)}function c(){if(n){var r,i,o=n.length;for(e=new Array(o),r=0;r[u(t,n,r),t])));for(a=0,i=new Array(f);a=u)){(t.data!==n||t.next)&&(0===l&&(p+=(l=Uc(e))*l),0===h&&(p+=(h=Uc(e))*h),p(t=(Lc*t+jc)%Hc)/Hc}();function l(){h(),f.call("tick",n),e1?(null==e?u.delete(t):u.set(t,p(e)),n):u.get(t)},find:function(n,e,r){var i,o,a,u,c,f=0,s=t.length;for(null==r?r=1/0:r*=r,f=0;f1?(f.on(t,e),n):f.on(t)}}},t.forceX=function(t){var n,e,r,i=qc(.1);function o(t){for(var i,o=0,a=n.length;o=.12&&i<.234&&r>=-.425&&r<-.214?u:i>=.166&&i<.234&&r>=-.214&&r<-.115?c:a).invert(t)},s.stream=function(e){return t&&n===e?t:(r=[a.stream(n=e),u.stream(e),c.stream(e)],i=r.length,t={point:function(t,n){for(var e=-1;++ejs(r[0],r[1])&&(r[1]=i[1]),js(i[0],r[1])>js(r[0],r[1])&&(r[0]=i[0])):o.push(r=i);for(a=-1/0,n=0,r=o[e=o.length-1];n<=e;r=i,++n)i=o[n],(u=js(r[1],i[0]))>a&&(a=u,Wf=i[0],Kf=r[1])}return is=os=null,Wf===1/0||Zf===1/0?[[NaN,NaN],[NaN,NaN]]:[[Wf,Zf],[Kf,Qf]]},t.geoCentroid=function(t){ms=xs=ws=Ms=Ts=As=Ss=Es=0,Ns=new T,ks=new T,Cs=new T,Lf(t,Gs);var n=+Ns,e=+ks,r=+Cs,i=Ef(n,e,r);return i=0))throw new RangeError(`invalid digits: ${t}`);i=n}return null===n&&(r=new ed(i)),a},a.projection(t).digits(i).context(n)},t.geoProjection=yd,t.geoProjectionMutator=vd,t.geoRotation=ll,t.geoStereographic=function(){return yd(Bd).scale(250).clipAngle(142)},t.geoStereographicRaw=Bd,t.geoStream=Lf,t.geoTransform=function(t){return{stream:id(t)}},t.geoTransverseMercator=function(){var t=Ed(Yd),n=t.center,e=t.rotate;return t.center=function(t){return arguments.length?n([-t[1],t[0]]):[(t=n())[1],-t[0]]},t.rotate=function(t){return arguments.length?e([t[0],t[1],t.length>2?t[2]+90:90]):[(t=e())[0],t[1],t[2]-90]},e([0,0,90]).scale(159.155)},t.geoTransverseMercatorRaw=Yd,t.gray=function(t,n){return new ur(t,0,0,null==n?1:n)},t.greatest=ot,t.greatestIndex=function(t,e=n){if(1===e.length)return tt(t,e);let r,i=-1,o=-1;for(const n of t)++o,(i<0?0===e(n,n):e(n,r)>0)&&(r=n,i=o);return i},t.group=C,t.groupSort=function(t,e,r){return(2!==e.length?U($(t,e,r),(([t,e],[r,i])=>n(e,i)||n(t,r))):U(C(t,r),(([t,r],[i,o])=>e(r,o)||n(t,i)))).map((([t])=>t))},t.groups=P,t.hcl=dr,t.hierarchy=Gd,t.histogram=Q,t.hsl=He,t.html=Ec,t.image=function(t,n){return new Promise((function(e,r){var i=new Image;for(var o in n)i[o]=n[o];i.onerror=r,i.onload=function(){e(i)},i.src=t}))},t.index=function(t,...n){return F(t,k,R,n)},t.indexes=function(t,...n){return F(t,Array.from,R,n)},t.interpolate=Gr,t.interpolateArray=function(t,n){return(Ir(n)?Ur:Or)(t,n)},t.interpolateBasis=Er,t.interpolateBasisClosed=Nr,t.interpolateBlues=Gb,t.interpolateBrBG=ob,t.interpolateBuGn=Mb,t.interpolateBuPu=Ab,t.interpolateCividis=function(t){return t=Math.max(0,Math.min(1,t)),"rgb("+Math.max(0,Math.min(255,Math.round(-4.54-t*(35.34-t*(2381.73-t*(6402.7-t*(7024.72-2710.57*t)))))))+", "+Math.max(0,Math.min(255,Math.round(32.49+t*(170.73+t*(52.82-t*(131.46-t*(176.58-67.37*t)))))))+", "+Math.max(0,Math.min(255,Math.round(81.24+t*(442.36-t*(2482.43-t*(6167.24-t*(6614.94-2475.67*t)))))))+")"},t.interpolateCool=am,t.interpolateCubehelix=li,t.interpolateCubehelixDefault=im,t.interpolateCubehelixLong=hi,t.interpolateDate=Br,t.interpolateDiscrete=function(t){var n=t.length;return function(e){return t[Math.max(0,Math.min(n-1,Math.floor(e*n)))]}},t.interpolateGnBu=Eb,t.interpolateGreens=Wb,t.interpolateGreys=Kb,t.interpolateHcl=ci,t.interpolateHclLong=fi,t.interpolateHsl=oi,t.interpolateHslLong=ai,t.interpolateHue=function(t,n){var e=Pr(+t,+n);return function(t){var n=e(t);return n-360*Math.floor(n/360)}},t.interpolateInferno=pm,t.interpolateLab=function(t,n){var e=$r((t=ar(t)).l,(n=ar(n)).l),r=$r(t.a,n.a),i=$r(t.b,n.b),o=$r(t.opacity,n.opacity);return function(n){return t.l=e(n),t.a=r(n),t.b=i(n),t.opacity=o(n),t+""}},t.interpolateMagma=dm,t.interpolateNumber=Yr,t.interpolateNumberArray=Ur,t.interpolateObject=Lr,t.interpolateOrRd=kb,t.interpolateOranges=rm,t.interpolatePRGn=ub,t.interpolatePiYG=fb,t.interpolatePlasma=gm,t.interpolatePuBu=$b,t.interpolatePuBuGn=Pb,t.interpolatePuOr=lb,t.interpolatePuRd=Rb,t.interpolatePurples=Jb,t.interpolateRainbow=function(t){(t<0||t>1)&&(t-=Math.floor(t));var n=Math.abs(t-.5);return um.h=360*t-100,um.s=1.5-1.5*n,um.l=.8-.9*n,um+""},t.interpolateRdBu=db,t.interpolateRdGy=gb,t.interpolateRdPu=qb,t.interpolateRdYlBu=vb,t.interpolateRdYlGn=bb,t.interpolateReds=nm,t.interpolateRgb=Dr,t.interpolateRgbBasis=Fr,t.interpolateRgbBasisClosed=qr,t.interpolateRound=Vr,t.interpolateSinebow=function(t){var n;return t=(.5-t)*Math.PI,cm.r=255*(n=Math.sin(t))*n,cm.g=255*(n=Math.sin(t+fm))*n,cm.b=255*(n=Math.sin(t+sm))*n,cm+""},t.interpolateSpectral=xb,t.interpolateString=Xr,t.interpolateTransformCss=ti,t.interpolateTransformSvg=ni,t.interpolateTurbo=function(t){return t=Math.max(0,Math.min(1,t)),"rgb("+Math.max(0,Math.min(255,Math.round(34.61+t*(1172.33-t*(10793.56-t*(33300.12-t*(38394.49-14825.05*t)))))))+", "+Math.max(0,Math.min(255,Math.round(23.31+t*(557.33+t*(1225.33-t*(3574.96-t*(1073.77+707.56*t)))))))+", "+Math.max(0,Math.min(255,Math.round(27.2+t*(3211.1-t*(15327.97-t*(27814-t*(22569.18-6838.66*t)))))))+")"},t.interpolateViridis=hm,t.interpolateWarm=om,t.interpolateYlGn=Bb,t.interpolateYlGnBu=Ib,t.interpolateYlOrBr=Lb,t.interpolateYlOrRd=Hb,t.interpolateZoom=ri,t.interrupt=Gi,t.intersection=function(t,...n){t=new InternSet(t),n=n.map(vt);t:for(const e of t)for(const r of n)if(!r.has(e)){t.delete(e);continue t}return t},t.interval=function(t,n,e){var r=new Ei,i=n;return null==n?(r.restart(t,n,e),r):(r._restart=r.restart,r.restart=function(t,n,e){n=+n,e=null==e?Ai():+e,r._restart((function o(a){a+=i,r._restart(o,i+=n,e),t(a)}),n,e)},r.restart(t,n,e),r)},t.isoFormat=D_,t.isoParse=F_,t.json=function(t,n){return fetch(t,n).then(Tc)},t.lab=ar,t.lch=function(t,n,e,r){return 1===arguments.length?hr(t):new pr(e,n,t,null==r?1:r)},t.least=function(t,e=n){let r,i=!1;if(1===e.length){let o;for(const a of t){const t=e(a);(i?n(t,o)<0:0===n(t,t))&&(r=a,o=t,i=!0)}}else for(const n of t)(i?e(n,r)<0:0===e(n,n))&&(r=n,i=!0);return r},t.leastIndex=ht,t.line=Ym,t.lineRadial=Zm,t.link=ax,t.linkHorizontal=function(){return ax(nx)},t.linkRadial=function(){const t=ax(rx);return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t},t.linkVertical=function(){return ax(ex)},t.local=Qn,t.map=function(t,n){if("function"!=typeof t[Symbol.iterator])throw new TypeError("values is not iterable");if("function"!=typeof n)throw new TypeError("mapper is not a function");return Array.from(t,((e,r)=>n(e,r,t)))},t.matcher=Vt,t.max=J,t.maxIndex=tt,t.mean=function(t,n){let e=0,r=0;if(void 0===n)for(let n of t)null!=n&&(n=+n)>=n&&(++e,r+=n);else{let i=-1;for(let o of t)null!=(o=n(o,++i,t))&&(o=+o)>=o&&(++e,r+=o)}if(e)return r/e},t.median=function(t,n){return at(t,.5,n)},t.medianIndex=function(t,n){return ct(t,.5,n)},t.merge=ft,t.min=nt,t.minIndex=et,t.mode=function(t,n){const e=new InternMap;if(void 0===n)for(let n of t)null!=n&&n>=n&&e.set(n,(e.get(n)||0)+1);else{let r=-1;for(let i of t)null!=(i=n(i,++r,t))&&i>=i&&e.set(i,(e.get(i)||0)+1)}let r,i=0;for(const[t,n]of e)n>i&&(i=n,r=t);return r},t.namespace=It,t.namespaces=Ut,t.nice=Z,t.now=Ai,t.pack=function(){var t=null,n=1,e=1,r=np;function i(i){const o=ap();return i.x=n/2,i.y=e/2,t?i.eachBefore(xp(t)).eachAfter(wp(r,.5,o)).eachBefore(Mp(1)):i.eachBefore(xp(mp)).eachAfter(wp(np,1,o)).eachAfter(wp(r,i.r/Math.min(n,e),o)).eachBefore(Mp(Math.min(n,e)/(2*i.r))),i}return i.radius=function(n){return arguments.length?(t=Jd(n),i):t},i.size=function(t){return arguments.length?(n=+t[0],e=+t[1],i):[n,e]},i.padding=function(t){return arguments.length?(r="function"==typeof t?t:ep(+t),i):r},i},t.packEnclose=function(t){return up(t,ap())},t.packSiblings=function(t){return bp(t,ap()),t},t.pairs=function(t,n=st){const e=[];let r,i=!1;for(const o of t)i&&e.push(n(r,o)),r=o,i=!0;return e},t.partition=function(){var t=1,n=1,e=0,r=!1;function i(i){var o=i.height+1;return i.x0=i.y0=e,i.x1=t,i.y1=n/o,i.eachBefore(function(t,n){return function(r){r.children&&Ap(r,r.x0,t*(r.depth+1)/n,r.x1,t*(r.depth+2)/n);var i=r.x0,o=r.y0,a=r.x1-e,u=r.y1-e;a0&&(d+=l);for(null!=n?p.sort((function(t,e){return n(g[t],g[e])})):null!=e&&p.sort((function(t,n){return e(a[t],a[n])})),u=0,f=d?(v-h*b)/d:0;u0?l*f:0)+b,g[c]={data:a[c],index:u,value:l,startAngle:y,endAngle:s,padAngle:_};return g}return a.value=function(n){return arguments.length?(t="function"==typeof n?n:ym(+n),a):t},a.sortValues=function(t){return arguments.length?(n=t,e=null,a):n},a.sort=function(t){return arguments.length?(e=t,n=null,a):e},a.startAngle=function(t){return arguments.length?(r="function"==typeof t?t:ym(+t),a):r},a.endAngle=function(t){return arguments.length?(i="function"==typeof t?t:ym(+t),a):i},a.padAngle=function(t){return arguments.length?(o="function"==typeof t?t:ym(+t),a):o},a},t.piecewise=di,t.pointRadial=Qm,t.pointer=ne,t.pointers=function(t,n){return t.target&&(t=te(t),void 0===n&&(n=t.currentTarget),t=t.touches||[t]),Array.from(t,(t=>ne(t,n)))},t.polygonArea=function(t){for(var n,e=-1,r=t.length,i=t[r-1],o=0;++eu!=f>u&&a<(c-e)*(u-r)/(f-r)+e&&(s=!s),c=e,f=r;return s},t.polygonHull=function(t){if((e=t.length)<3)return null;var n,e,r=new Array(e),i=new Array(e);for(n=0;n=0;--n)f.push(t[r[o[n]][2]]);for(n=+u;n(n=1664525*n+1013904223|0,lg*(n>>>0))},t.randomLogNormal=Kp,t.randomLogistic=fg,t.randomNormal=Zp,t.randomPareto=ng,t.randomPoisson=sg,t.randomUniform=Vp,t.randomWeibull=ug,t.range=lt,t.rank=function(t,e=n){if("function"!=typeof t[Symbol.iterator])throw new TypeError("values is not iterable");let r=Array.from(t);const i=new Float64Array(r.length);2!==e.length&&(r=r.map(e),e=n);const o=(t,n)=>e(r[t],r[n]);let a,u;return(t=Uint32Array.from(r,((t,n)=>n))).sort(e===n?(t,n)=>O(r[t],r[n]):I(o)),t.forEach(((t,n)=>{const e=o(t,void 0===a?t:a);e>=0?((void 0===a||e>0)&&(a=t,u=n),i[t]=u):i[t]=NaN})),i},t.reduce=function(t,n,e){if("function"!=typeof n)throw new TypeError("reducer is not a function");const r=t[Symbol.iterator]();let i,o,a=-1;if(arguments.length<3){if(({done:i,value:e}=r.next()),i)return;++a}for(;({done:i,value:o}=r.next()),!i;)e=n(e,o,++a,t);return e},t.reverse=function(t){if("function"!=typeof t[Symbol.iterator])throw new TypeError("values is not iterable");return Array.from(t).reverse()},t.rgb=Fe,t.ribbon=function(){return Wa()},t.ribbonArrow=function(){return Wa(Va)},t.rollup=$,t.rollups=D,t.scaleBand=yg,t.scaleDiverging=function t(){var n=Ng(L_()(mg));return n.copy=function(){return B_(n,t())},dg.apply(n,arguments)},t.scaleDivergingLog=function t(){var n=Fg(L_()).domain([.1,1,10]);return n.copy=function(){return B_(n,t()).base(n.base())},dg.apply(n,arguments)},t.scaleDivergingPow=j_,t.scaleDivergingSqrt=function(){return j_.apply(null,arguments).exponent(.5)},t.scaleDivergingSymlog=function t(){var n=Ig(L_());return n.copy=function(){return B_(n,t()).constant(n.constant())},dg.apply(n,arguments)},t.scaleIdentity=function t(n){var e;function r(t){return null==t||isNaN(t=+t)?e:t}return r.invert=r,r.domain=r.range=function(t){return arguments.length?(n=Array.from(t,_g),r):n.slice()},r.unknown=function(t){return arguments.length?(e=t,r):e},r.copy=function(){return t(n).unknown(e)},n=arguments.length?Array.from(n,_g):[0,1],Ng(r)},t.scaleImplicit=pg,t.scaleLinear=function t(){var n=Sg();return n.copy=function(){return Tg(n,t())},hg.apply(n,arguments),Ng(n)},t.scaleLog=function t(){const n=Fg(Ag()).domain([1,10]);return n.copy=()=>Tg(n,t()).base(n.base()),hg.apply(n,arguments),n},t.scaleOrdinal=gg,t.scalePoint=function(){return vg(yg.apply(null,arguments).paddingInner(1))},t.scalePow=jg,t.scaleQuantile=function t(){var e,r=[],i=[],o=[];function a(){var t=0,n=Math.max(1,i.length);for(o=new Array(n-1);++t0?o[n-1]:r[0],n=i?[o[i-1],r]:[o[n-1],o[n]]},u.unknown=function(t){return arguments.length?(n=t,u):u},u.thresholds=function(){return o.slice()},u.copy=function(){return t().domain([e,r]).range(a).unknown(n)},hg.apply(Ng(u),arguments)},t.scaleRadial=function t(){var n,e=Sg(),r=[0,1],i=!1;function o(t){var r=function(t){return Math.sign(t)*Math.sqrt(Math.abs(t))}(e(t));return isNaN(r)?n:i?Math.round(r):r}return o.invert=function(t){return e.invert(Hg(t))},o.domain=function(t){return arguments.length?(e.domain(t),o):e.domain()},o.range=function(t){return arguments.length?(e.range((r=Array.from(t,_g)).map(Hg)),o):r.slice()},o.rangeRound=function(t){return o.range(t).round(!0)},o.round=function(t){return arguments.length?(i=!!t,o):i},o.clamp=function(t){return arguments.length?(e.clamp(t),o):e.clamp()},o.unknown=function(t){return arguments.length?(n=t,o):n},o.copy=function(){return t(e.domain(),r).round(i).clamp(e.clamp()).unknown(n)},hg.apply(o,arguments),Ng(o)},t.scaleSequential=function t(){var n=Ng(O_()(mg));return n.copy=function(){return B_(n,t())},dg.apply(n,arguments)},t.scaleSequentialLog=function t(){var n=Fg(O_()).domain([1,10]);return n.copy=function(){return B_(n,t()).base(n.base())},dg.apply(n,arguments)},t.scaleSequentialPow=Y_,t.scaleSequentialQuantile=function t(){var e=[],r=mg;function i(t){if(null!=t&&!isNaN(t=+t))return r((s(e,t,1)-1)/(e.length-1))}return i.domain=function(t){if(!arguments.length)return e.slice();e=[];for(let n of t)null==n||isNaN(n=+n)||e.push(n);return e.sort(n),i},i.interpolator=function(t){return arguments.length?(r=t,i):r},i.range=function(){return e.map(((t,n)=>r(n/(e.length-1))))},i.quantiles=function(t){return Array.from({length:t+1},((n,r)=>at(e,r/t)))},i.copy=function(){return t(r).domain(e)},dg.apply(i,arguments)},t.scaleSequentialSqrt=function(){return Y_.apply(null,arguments).exponent(.5)},t.scaleSequentialSymlog=function t(){var n=Ig(O_());return n.copy=function(){return B_(n,t()).constant(n.constant())},dg.apply(n,arguments)},t.scaleSqrt=function(){return jg.apply(null,arguments).exponent(.5)},t.scaleSymlog=function t(){var n=Ig(Ag());return n.copy=function(){return Tg(n,t()).constant(n.constant())},hg.apply(n,arguments)},t.scaleThreshold=function t(){var n,e=[.5],r=[0,1],i=1;function o(t){return null!=t&&t<=t?r[s(e,t,0,i)]:n}return o.domain=function(t){return arguments.length?(e=Array.from(t),i=Math.min(e.length,r.length-1),o):e.slice()},o.range=function(t){return arguments.length?(r=Array.from(t),i=Math.min(e.length,r.length-1),o):r.slice()},o.invertExtent=function(t){var n=r.indexOf(t);return[e[n-1],e[n]]},o.unknown=function(t){return arguments.length?(n=t,o):n},o.copy=function(){return t().domain(e).range(r).unknown(n)},hg.apply(o,arguments)},t.scaleTime=function(){return hg.apply(I_(uv,cv,tv,Zy,xy,py,sy,ay,iy,t.timeFormat).domain([new Date(2e3,0,1),new Date(2e3,0,2)]),arguments)},t.scaleUtc=function(){return hg.apply(I_(ov,av,ev,Qy,Fy,yy,hy,cy,iy,t.utcFormat).domain([Date.UTC(2e3,0,1),Date.UTC(2e3,0,2)]),arguments)},t.scan=function(t,n){const e=ht(t,n);return e<0?void 0:e},t.schemeAccent=G_,t.schemeBlues=Xb,t.schemeBrBG=ib,t.schemeBuGn=wb,t.schemeBuPu=Tb,t.schemeCategory10=X_,t.schemeDark2=V_,t.schemeGnBu=Sb,t.schemeGreens=Vb,t.schemeGreys=Zb,t.schemeObservable10=W_,t.schemeOrRd=Nb,t.schemeOranges=em,t.schemePRGn=ab,t.schemePaired=Z_,t.schemePastel1=K_,t.schemePastel2=Q_,t.schemePiYG=cb,t.schemePuBu=zb,t.schemePuBuGn=Cb,t.schemePuOr=sb,t.schemePuRd=Db,t.schemePurples=Qb,t.schemeRdBu=hb,t.schemeRdGy=pb,t.schemeRdPu=Fb,t.schemeRdYlBu=yb,t.schemeRdYlGn=_b,t.schemeReds=tm,t.schemeSet1=J_,t.schemeSet2=tb,t.schemeSet3=nb,t.schemeSpectral=mb,t.schemeTableau10=eb,t.schemeYlGn=Ob,t.schemeYlGnBu=Ub,t.schemeYlOrBr=Yb,t.schemeYlOrRd=jb,t.select=Zn,t.selectAll=function(t){return"string"==typeof t?new Vn([document.querySelectorAll(t)],[document.documentElement]):new Vn([Ht(t)],Gn)},t.selection=Wn,t.selector=jt,t.selectorAll=Gt,t.shuffle=dt,t.shuffler=pt,t.some=function(t,n){if("function"!=typeof n)throw new TypeError("test is not a function");let e=-1;for(const r of t)if(n(r,++e,t))return!0;return!1},t.sort=U,t.stack=function(){var t=ym([]),n=dw,e=hw,r=pw;function i(i){var o,a,u=Array.from(t.apply(this,arguments),gw),c=u.length,f=-1;for(const t of i)for(o=0,++f;o0)for(var e,r,i,o,a,u,c=0,f=t[n[0]].length;c0?(r[0]=o,r[1]=o+=i):i<0?(r[1]=a,r[0]=a+=i):(r[0]=0,r[1]=i)},t.stackOffsetExpand=function(t,n){if((r=t.length)>0){for(var e,r,i,o=0,a=t[0].length;o0){for(var e,r=0,i=t[n[0]],o=i.length;r0&&(r=(e=t[n[0]]).length)>0){for(var e,r,i,o=0,a=1;afunction(t){t=`${t}`;let n=t.length;zp(t,n-1)&&!zp(t,n-2)&&(t=t.slice(0,-1));return"/"===t[0]?t:`/${t}`}(t(n,e,r)))),e=n.map(Pp),i=new Set(n).add("");for(const t of e)i.has(t)||(i.add(t),n.push(t),e.push(Pp(t)),h.push(Np));d=(t,e)=>n[e],p=(t,n)=>e[n]}for(a=0,i=h.length;a=0&&(f=h[t]).data===Np;--t)f.data=null}if(u.parent=Sp,u.eachBefore((function(t){t.depth=t.parent.depth+1,--i})).eachBefore(Kd),u.parent=null,i>0)throw new Error("cycle");return u}return r.id=function(t){return arguments.length?(n=Jd(t),r):n},r.parentId=function(t){return arguments.length?(e=Jd(t),r):e},r.path=function(n){return arguments.length?(t=Jd(n),r):t},r},t.style=_n,t.subset=function(t,n){return _t(n,t)},t.sum=function(t,n){let e=0;if(void 0===n)for(let n of t)(n=+n)&&(e+=n);else{let r=-1;for(let i of t)(i=+n(i,++r,t))&&(e+=i)}return e},t.superset=_t,t.svg=Nc,t.symbol=function(t,n){let e=null,r=km(i);function i(){let i;if(e||(e=i=r()),t.apply(this,arguments).draw(e,+n.apply(this,arguments)),i)return e=null,i+""||null}return t="function"==typeof t?t:ym(t||fx),n="function"==typeof n?n:ym(void 0===n?64:+n),i.type=function(n){return arguments.length?(t="function"==typeof n?n:ym(n),i):t},i.size=function(t){return arguments.length?(n="function"==typeof t?t:ym(+t),i):n},i.context=function(t){return arguments.length?(e=null==t?null:t,i):e},i},t.symbolAsterisk=cx,t.symbolCircle=fx,t.symbolCross=sx,t.symbolDiamond=dx,t.symbolDiamond2=px,t.symbolPlus=gx,t.symbolSquare=yx,t.symbolSquare2=vx,t.symbolStar=xx,t.symbolTimes=Px,t.symbolTriangle=Mx,t.symbolTriangle2=Ax,t.symbolWye=Cx,t.symbolX=Px,t.symbols=zx,t.symbolsFill=zx,t.symbolsStroke=$x,t.text=mc,t.thresholdFreedmanDiaconis=function(t,n,e){const r=v(t),i=at(t,.75)-at(t,.25);return r&&i?Math.ceil((e-n)/(2*i*Math.pow(r,-1/3))):1},t.thresholdScott=function(t,n,e){const r=v(t),i=w(t);return r&&i?Math.ceil((e-n)*Math.cbrt(r)/(3.49*i)):1},t.thresholdSturges=K,t.tickFormat=Eg,t.tickIncrement=V,t.tickStep=W,t.ticks=G,t.timeDay=py,t.timeDays=gy,t.timeFormatDefaultLocale=P_,t.timeFormatLocale=hv,t.timeFriday=Sy,t.timeFridays=$y,t.timeHour=sy,t.timeHours=ly,t.timeInterval=Vg,t.timeMillisecond=Wg,t.timeMilliseconds=Zg,t.timeMinute=ay,t.timeMinutes=uy,t.timeMonday=wy,t.timeMondays=ky,t.timeMonth=Zy,t.timeMonths=Ky,t.timeSaturday=Ey,t.timeSaturdays=Dy,t.timeSecond=iy,t.timeSeconds=oy,t.timeSunday=xy,t.timeSundays=Ny,t.timeThursday=Ay,t.timeThursdays=zy,t.timeTickInterval=cv,t.timeTicks=uv,t.timeTuesday=My,t.timeTuesdays=Cy,t.timeWednesday=Ty,t.timeWednesdays=Py,t.timeWeek=xy,t.timeWeeks=Ny,t.timeYear=tv,t.timeYears=nv,t.timeout=$i,t.timer=Ni,t.timerFlush=ki,t.transition=go,t.transpose=gt,t.tree=function(){var t=$p,n=1,e=1,r=null;function i(i){var c=function(t){for(var n,e,r,i,o,a=new Up(t,0),u=[a];n=u.pop();)if(r=n._.children)for(n.children=new Array(o=r.length),i=o-1;i>=0;--i)u.push(e=n.children[i]=new Up(r[i],i)),e.parent=n;return(a.parent=new Up(null,0)).children=[a],a}(i);if(c.eachAfter(o),c.parent.m=-c.z,c.eachBefore(a),r)i.eachBefore(u);else{var f=i,s=i,l=i;i.eachBefore((function(t){t.xs.x&&(s=t),t.depth>l.depth&&(l=t)}));var h=f===s?1:t(f,s)/2,d=h-f.x,p=n/(s.x+h+d),g=e/(l.depth||1);i.eachBefore((function(t){t.x=(t.x+d)*p,t.y=t.depth*g}))}return i}function o(n){var e=n.children,r=n.parent.children,i=n.i?r[n.i-1]:null;if(e){!function(t){for(var n,e=0,r=0,i=t.children,o=i.length;--o>=0;)(n=i[o]).z+=e,n.m+=e,e+=n.s+(r+=n.c)}(n);var o=(e[0].z+e[e.length-1].z)/2;i?(n.z=i.z+t(n._,i._),n.m=n.z-o):n.z=o}else i&&(n.z=i.z+t(n._,i._));n.parent.A=function(n,e,r){if(e){for(var i,o=n,a=n,u=e,c=o.parent.children[0],f=o.m,s=a.m,l=u.m,h=c.m;u=Rp(u),o=Dp(o),u&&o;)c=Dp(c),(a=Rp(a)).a=n,(i=u.z+l-o.z-f+t(u._,o._))>0&&(Fp(qp(u,n,r),n,i),f+=i,s+=i),l+=u.m,f+=o.m,h+=c.m,s+=a.m;u&&!Rp(a)&&(a.t=u,a.m+=l-s),o&&!Dp(c)&&(c.t=o,c.m+=f-h,r=n)}return r}(n,i,n.parent.A||r[0])}function a(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function u(t){t.x*=n,t.y=t.depth*e}return i.separation=function(n){return arguments.length?(t=n,i):t},i.size=function(t){return arguments.length?(r=!1,n=+t[0],e=+t[1],i):r?null:[n,e]},i.nodeSize=function(t){return arguments.length?(r=!0,n=+t[0],e=+t[1],i):r?[n,e]:null},i},t.treemap=function(){var t=Yp,n=!1,e=1,r=1,i=[0],o=np,a=np,u=np,c=np,f=np;function s(t){return t.x0=t.y0=0,t.x1=e,t.y1=r,t.eachBefore(l),i=[0],n&&t.eachBefore(Tp),t}function l(n){var e=i[n.depth],r=n.x0+e,s=n.y0+e,l=n.x1-e,h=n.y1-e;l=e-1){var s=u[n];return s.x0=i,s.y0=o,s.x1=a,void(s.y1=c)}var l=f[n],h=r/2+l,d=n+1,p=e-1;for(;d>>1;f[g]c-o){var _=r?(i*v+a*y)/r:a;t(n,d,y,i,o,_,c),t(d,e,v,_,o,a,c)}else{var b=r?(o*v+c*y)/r:c;t(n,d,y,i,o,a,b),t(d,e,v,i,b,a,c)}}(0,c,t.value,n,e,r,i)},t.treemapDice=Ap,t.treemapResquarify=Lp,t.treemapSlice=Ip,t.treemapSliceDice=function(t,n,e,r,i){(1&t.depth?Ip:Ap)(t,n,e,r,i)},t.treemapSquarify=Yp,t.tsv=Mc,t.tsvFormat=lc,t.tsvFormatBody=hc,t.tsvFormatRow=pc,t.tsvFormatRows=dc,t.tsvFormatValue=gc,t.tsvParse=fc,t.tsvParseRows=sc,t.union=function(...t){const n=new InternSet;for(const e of t)for(const t of e)n.add(t);return n},t.unixDay=_y,t.unixDays=by,t.utcDay=yy,t.utcDays=vy,t.utcFriday=By,t.utcFridays=Vy,t.utcHour=hy,t.utcHours=dy,t.utcMillisecond=Wg,t.utcMilliseconds=Zg,t.utcMinute=cy,t.utcMinutes=fy,t.utcMonday=qy,t.utcMondays=jy,t.utcMonth=Qy,t.utcMonths=Jy,t.utcSaturday=Yy,t.utcSaturdays=Wy,t.utcSecond=iy,t.utcSeconds=oy,t.utcSunday=Fy,t.utcSundays=Ly,t.utcThursday=Oy,t.utcThursdays=Gy,t.utcTickInterval=av,t.utcTicks=ov,t.utcTuesday=Uy,t.utcTuesdays=Hy,t.utcWednesday=Iy,t.utcWednesdays=Xy,t.utcWeek=Fy,t.utcWeeks=Ly,t.utcYear=ev,t.utcYears=rv,t.variance=x,t.version="7.9.0",t.window=pn,t.xml=Sc,t.zip=function(){return gt(arguments)},t.zoom=function(){var t,n,e,r=Ew,i=Nw,o=zw,a=Cw,u=Pw,c=[0,1/0],f=[[-1/0,-1/0],[1/0,1/0]],s=250,l=ri,h=$t("start","zoom","end"),d=500,p=150,g=0,y=10;function v(t){t.property("__zoom",kw).on("wheel.zoom",T,{passive:!1}).on("mousedown.zoom",A).on("dblclick.zoom",S).filter(u).on("touchstart.zoom",E).on("touchmove.zoom",N).on("touchend.zoom touchcancel.zoom",k).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function _(t,n){return(n=Math.max(c[0],Math.min(c[1],n)))===t.k?t:new ww(n,t.x,t.y)}function b(t,n,e){var r=n[0]-e[0]*t.k,i=n[1]-e[1]*t.k;return r===t.x&&i===t.y?t:new ww(t.k,r,i)}function m(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function x(t,n,e,r){t.on("start.zoom",(function(){w(this,arguments).event(r).start()})).on("interrupt.zoom end.zoom",(function(){w(this,arguments).event(r).end()})).tween("zoom",(function(){var t=this,o=arguments,a=w(t,o).event(r),u=i.apply(t,o),c=null==e?m(u):"function"==typeof e?e.apply(t,o):e,f=Math.max(u[1][0]-u[0][0],u[1][1]-u[0][1]),s=t.__zoom,h="function"==typeof n?n.apply(t,o):n,d=l(s.invert(c).concat(f/s.k),h.invert(c).concat(f/h.k));return function(t){if(1===t)t=h;else{var n=d(t),e=f/n[2];t=new ww(e,c[0]-n[0]*e,c[1]-n[1]*e)}a.zoom(null,t)}}))}function w(t,n,e){return!e&&t.__zooming||new M(t,n)}function M(t,n){this.that=t,this.args=n,this.active=0,this.sourceEvent=null,this.extent=i.apply(t,n),this.taps=0}function T(t,...n){if(r.apply(this,arguments)){var e=w(this,n).event(t),i=this.__zoom,u=Math.max(c[0],Math.min(c[1],i.k*Math.pow(2,a.apply(this,arguments)))),s=ne(t);if(e.wheel)e.mouse[0][0]===s[0]&&e.mouse[0][1]===s[1]||(e.mouse[1]=i.invert(e.mouse[0]=s)),clearTimeout(e.wheel);else{if(i.k===u)return;e.mouse=[s,i.invert(s)],Gi(this),e.start()}Sw(t),e.wheel=setTimeout((function(){e.wheel=null,e.end()}),p),e.zoom("mouse",o(b(_(i,u),e.mouse[0],e.mouse[1]),e.extent,f))}}function A(t,...n){if(!e&&r.apply(this,arguments)){var i=t.currentTarget,a=w(this,n,!0).event(t),u=Zn(t.view).on("mousemove.zoom",(function(t){if(Sw(t),!a.moved){var n=t.clientX-s,e=t.clientY-l;a.moved=n*n+e*e>g}a.event(t).zoom("mouse",o(b(a.that.__zoom,a.mouse[0]=ne(t,i),a.mouse[1]),a.extent,f))}),!0).on("mouseup.zoom",(function(t){u.on("mousemove.zoom mouseup.zoom",null),ue(t.view,a.moved),Sw(t),a.event(t).end()}),!0),c=ne(t,i),s=t.clientX,l=t.clientY;ae(t.view),Aw(t),a.mouse=[c,this.__zoom.invert(c)],Gi(this),a.start()}}function S(t,...n){if(r.apply(this,arguments)){var e=this.__zoom,a=ne(t.changedTouches?t.changedTouches[0]:t,this),u=e.invert(a),c=e.k*(t.shiftKey?.5:2),l=o(b(_(e,c),a,u),i.apply(this,n),f);Sw(t),s>0?Zn(this).transition().duration(s).call(x,l,a,t):Zn(this).call(v.transform,l,a,t)}}function E(e,...i){if(r.apply(this,arguments)){var o,a,u,c,f=e.touches,s=f.length,l=w(this,i,e.changedTouches.length===s).event(e);for(Aw(e),a=0;a.vis-custom-time-marker{background-color:inherit;color:#fff;cursor:auto;font-size:12px;padding:3px 5px;top:0;white-space:nowrap;z-index:inherit}.vis-current-time{background-color:#ff7f6e;pointer-events:none;width:2px;z-index:1}.vis-rolling-mode-btn{background:#3876c2;border-radius:50%;color:#fff;cursor:pointer;font-size:28px;font-weight:700;height:40px;opacity:.8;position:absolute;right:20px;text-align:center;top:7px;width:40px}.vis-rolling-mode-btn:before{content:"\26F6"}.vis-rolling-mode-btn:hover{opacity:1}.vis-panel{box-sizing:border-box;margin:0;padding:0;position:absolute}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right,.vis-panel.vis-top{border:1px #bfbfbf}.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right{border-bottom-style:solid;border-top-style:solid;overflow:hidden}.vis-left.vis-panel.vis-vertical-scroll,.vis-right.vis-panel.vis-vertical-scroll{height:100%;overflow-x:hidden;overflow-y:scroll}.vis-left.vis-panel.vis-vertical-scroll{direction:rtl}.vis-left.vis-panel.vis-vertical-scroll .vis-content,.vis-right.vis-panel.vis-vertical-scroll{direction:ltr}.vis-right.vis-panel.vis-vertical-scroll .vis-content{direction:rtl}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-top{border-left-style:solid;border-right-style:solid}.vis-background{overflow:hidden}.vis-panel>.vis-content{position:relative}.vis-panel .vis-shadow{box-shadow:0 0 10px rgba(0,0,0,.8);height:1px;position:absolute;width:100%}.vis-panel .vis-shadow.vis-top{left:0;top:-1px}.vis-panel .vis-shadow.vis-bottom{bottom:-1px;left:0}.vis-graph-group0{fill:#4f81bd;fill-opacity:0;stroke-width:2px;stroke:#4f81bd}.vis-graph-group1{fill:#f79646;fill-opacity:0;stroke-width:2px;stroke:#f79646}.vis-graph-group2{fill:#8c51cf;fill-opacity:0;stroke-width:2px;stroke:#8c51cf}.vis-graph-group3{fill:#75c841;fill-opacity:0;stroke-width:2px;stroke:#75c841}.vis-graph-group4{fill:#ff0100;fill-opacity:0;stroke-width:2px;stroke:#ff0100}.vis-graph-group5{fill:#37d8e6;fill-opacity:0;stroke-width:2px;stroke:#37d8e6}.vis-graph-group6{fill:#042662;fill-opacity:0;stroke-width:2px;stroke:#042662}.vis-graph-group7{fill:#00ff26;fill-opacity:0;stroke-width:2px;stroke:#00ff26}.vis-graph-group8{fill:#f0f;fill-opacity:0;stroke-width:2px;stroke:#f0f}.vis-graph-group9{fill:#8f3938;fill-opacity:0;stroke-width:2px;stroke:#8f3938}.vis-timeline .vis-fill{fill-opacity:.1;stroke:none}.vis-timeline .vis-bar{fill-opacity:.5;stroke-width:1px}.vis-timeline .vis-point{stroke-width:2px;fill-opacity:1}.vis-timeline .vis-legend-background{stroke-width:1px;fill-opacity:.9;fill:#fff;stroke:#c2c2c2}.vis-timeline .vis-outline{stroke-width:1px;fill-opacity:1;fill:#fff;stroke:#e5e5e5}.vis-timeline .vis-icon-fill{fill-opacity:.3;stroke:none}.vis-timeline{border:1px solid #bfbfbf;box-sizing:border-box;margin:0;overflow:hidden;padding:0;position:relative}.vis-loading-screen{height:100%;left:0;position:absolute;top:0;width:100%}.vis [class*=span]{min-height:0;width:auto}.vis-item{background-color:#d5ddf6;border-color:#97b0f8;border-width:1px;color:#1a1a1a;display:inline-block;position:absolute;z-index:1}.vis-item.vis-selected{background-color:#fff785;border-color:#ffc200;z-index:2}.vis-editable.vis-selected{cursor:move}.vis-item.vis-point.vis-selected{background-color:#fff785}.vis-item.vis-box{border-radius:2px;border-style:solid;text-align:center}.vis-item.vis-point{background:none}.vis-item.vis-dot{border-radius:4px;border-style:solid;border-width:4px;padding:0;position:absolute}.vis-item.vis-range{border-radius:2px;border-style:solid;box-sizing:border-box}.vis-item.vis-background{background-color:rgba(213,221,246,.4);border:none;box-sizing:border-box;margin:0;padding:0}.vis-item .vis-item-overflow{height:100%;margin:0;overflow:hidden;padding:0;position:relative;width:100%}.vis-item-visible-frame{white-space:nowrap}.vis-item.vis-range .vis-item-content{display:inline-block;position:relative}.vis-item.vis-background .vis-item-content{display:inline-block;position:absolute}.vis-item.vis-line{border-left-style:solid;border-left-width:1px;padding:0;position:absolute;width:0}.vis-item .vis-item-content{box-sizing:border-box;padding:5px;white-space:nowrap}.vis-item .vis-onUpdateTime-tooltip{background:#4f81bd;border-radius:1px;color:#fff;padding:5px;position:absolute;text-align:center;transition:.4s;-o-transition:.4s;-moz-transition:.4s;-webkit-transition:.4s;white-space:nowrap;width:200px}.vis-item .vis-delete,.vis-item .vis-delete-rtl{box-sizing:border-box;cursor:pointer;height:24px;padding:0 5px;position:absolute;top:0;-webkit-transition:background .2s linear;-moz-transition:background .2s linear;-ms-transition:background .2s linear;-o-transition:background .2s linear;transition:background .2s linear;width:24px}.vis-item .vis-delete{right:-24px}.vis-item .vis-delete-rtl{left:-24px}.vis-item .vis-delete-rtl:after,.vis-item .vis-delete:after{color:red;content:"\00D7";font-family:arial,sans-serif;font-size:22px;font-weight:700;-webkit-transition:color .2s linear;-moz-transition:color .2s linear;-ms-transition:color .2s linear;-o-transition:color .2s linear;transition:color .2s linear}.vis-item .vis-delete-rtl:hover,.vis-item .vis-delete:hover{background:red}.vis-item .vis-delete-rtl:hover:after,.vis-item .vis-delete:hover:after{color:#fff}.vis-item .vis-drag-center{cursor:move;height:100%;left:0;position:absolute;top:0;width:100%}.vis-item.vis-range .vis-drag-left{cursor:w-resize;left:-4px}.vis-item.vis-range .vis-drag-left,.vis-item.vis-range .vis-drag-right{height:100%;max-width:20%;min-width:2px;position:absolute;top:0;width:24px}.vis-item.vis-range .vis-drag-right{cursor:e-resize;right:-4px}.vis-range.vis-item.vis-readonly .vis-drag-left,.vis-range.vis-item.vis-readonly .vis-drag-right{cursor:auto}.vis-item.vis-cluster{border-radius:2px;border-style:solid;text-align:center;vertical-align:center}.vis-item.vis-cluster-line{border-left-style:solid;border-left-width:1px;padding:0;position:absolute;width:0}.vis-item.vis-cluster-dot{border-radius:4px;border-style:solid;border-width:4px;padding:0;position:absolute}div.vis-tooltip{background-color:#f5f4ed;border:1px solid #808074;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;box-shadow:3px 3px 10px rgba(0,0,0,.2);color:#000;font-family:verdana;font-size:14px;padding:5px;pointer-events:none;position:absolute;visibility:hidden;white-space:nowrap;z-index:5}.vis-itemset{box-sizing:border-box;margin:0;padding:0;position:relative}.vis-itemset .vis-background,.vis-itemset .vis-foreground{height:100%;overflow:visible;position:absolute;width:100%}.vis-axis{height:0;left:0;position:absolute;width:100%;z-index:1}.vis-foreground .vis-group{border-bottom:1px solid #bfbfbf;box-sizing:border-box;position:relative}.vis-foreground .vis-group:last-child{border-bottom:none}.vis-nesting-group{cursor:pointer}.vis-label.vis-nested-group.vis-group-level-unknown-but-gte1{background:#f5f5f5}.vis-label.vis-nested-group.vis-group-level-0{background-color:#fff}.vis-ltr .vis-label.vis-nested-group.vis-group-level-0 .vis-inner{padding-left:0}.vis-rtl .vis-label.vis-nested-group.vis-group-level-0 .vis-inner{padding-right:0}.vis-label.vis-nested-group.vis-group-level-1{background-color:rgba(0,0,0,.05)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-1 .vis-inner{padding-left:15px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-1 .vis-inner{padding-right:15px}.vis-label.vis-nested-group.vis-group-level-2{background-color:rgba(0,0,0,.1)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-2 .vis-inner{padding-left:30px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-2 .vis-inner{padding-right:30px}.vis-label.vis-nested-group.vis-group-level-3{background-color:rgba(0,0,0,.15)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-3 .vis-inner{padding-left:45px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-3 .vis-inner{padding-right:45px}.vis-label.vis-nested-group.vis-group-level-4{background-color:rgba(0,0,0,.2)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-4 .vis-inner{padding-left:60px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-4 .vis-inner{padding-right:60px}.vis-label.vis-nested-group.vis-group-level-5{background-color:rgba(0,0,0,.25)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-5 .vis-inner{padding-left:75px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-5 .vis-inner{padding-right:75px}.vis-label.vis-nested-group.vis-group-level-6{background-color:rgba(0,0,0,.3)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-6 .vis-inner{padding-left:90px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-6 .vis-inner{padding-right:90px}.vis-label.vis-nested-group.vis-group-level-7{background-color:rgba(0,0,0,.35)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-7 .vis-inner{padding-left:105px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-7 .vis-inner{padding-right:105px}.vis-label.vis-nested-group.vis-group-level-8{background-color:rgba(0,0,0,.4)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-8 .vis-inner{padding-left:120px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-8 .vis-inner{padding-right:120px}.vis-label.vis-nested-group.vis-group-level-9{background-color:rgba(0,0,0,.45)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-9 .vis-inner{padding-left:135px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-9 .vis-inner{padding-right:135px}.vis-label.vis-nested-group{background-color:rgba(0,0,0,.5)}.vis-ltr .vis-label.vis-nested-group .vis-inner{padding-left:150px}.vis-rtl .vis-label.vis-nested-group .vis-inner{padding-right:150px}.vis-group-level-unknown-but-gte1{border:1px solid red}.vis-label.vis-nesting-group:before{display:inline-block;width:15px}.vis-label.vis-nesting-group.expanded:before{content:"\25BC"}.vis-label.vis-nesting-group.collapsed:before{content:"\25B6"}.vis-rtl .vis-label.vis-nesting-group.collapsed:before{content:"\25C0"}.vis-ltr .vis-label:not(.vis-nesting-group):not(.vis-group-level-0){padding-left:15px}.vis-rtl .vis-label:not(.vis-nesting-group):not(.vis-group-level-0){padding-right:15px}.vis-overlay{height:100%;left:0;position:absolute;top:0;width:100%;z-index:10}.vis-labelset{overflow:hidden}.vis-labelset,.vis-labelset .vis-label{box-sizing:border-box;position:relative}.vis-labelset .vis-label{border-bottom:1px solid #bfbfbf;color:#4d4d4d;left:0;top:0;width:100%}.vis-labelset .vis-label.draggable{cursor:pointer}.vis-group-is-dragging{background:rgba(0,0,0,.1)}.vis-labelset .vis-label:last-child{border-bottom:none}.vis-labelset .vis-label .vis-inner{display:inline-block;padding:5px}.vis-labelset .vis-label .vis-inner.vis-hidden{padding:0}div.vis-configuration{display:block;float:left;font-size:12px;position:relative}div.vis-configuration-wrapper{display:block;width:700px}div.vis-configuration-wrapper:after{clear:both;content:"";display:block}div.vis-configuration.vis-config-option-container{background-color:#fff;border:2px solid #f7f8fa;border-radius:4px;display:block;left:10px;margin-top:20px;padding-left:5px;width:495px}div.vis-configuration.vis-config-button{background-color:#f7f8fa;border:2px solid #ceced0;border-radius:4px;cursor:pointer;display:block;height:25px;left:10px;line-height:25px;margin-bottom:30px;margin-top:20px;padding-left:5px;vertical-align:middle;width:495px}div.vis-configuration.vis-config-button.hover{background-color:#4588e6;border:2px solid #214373;color:#fff}div.vis-configuration.vis-config-item{display:block;float:left;height:25px;line-height:25px;vertical-align:middle;width:495px}div.vis-configuration.vis-config-item.vis-config-s2{background-color:#f7f8fa;border-radius:3px;left:10px;padding-left:5px}div.vis-configuration.vis-config-item.vis-config-s3{background-color:#e4e9f0;border-radius:3px;left:20px;padding-left:5px}div.vis-configuration.vis-config-item.vis-config-s4{background-color:#cfd8e6;border-radius:3px;left:30px;padding-left:5px}div.vis-configuration.vis-config-header{font-size:18px;font-weight:700}div.vis-configuration.vis-config-label{height:25px;line-height:25px;width:120px}div.vis-configuration.vis-config-label.vis-config-s3{width:110px}div.vis-configuration.vis-config-label.vis-config-s4{width:100px}div.vis-configuration.vis-config-colorBlock{border:1px solid #444;border-radius:2px;cursor:pointer;height:19px;margin:0;padding:0;top:1px;width:30px}input.vis-configuration.vis-config-checkbox{left:-5px}input.vis-configuration.vis-config-rangeinput{margin:0;padding:1px;pointer-events:none;position:relative;top:-5px;width:60px}input.vis-configuration.vis-config-range{-webkit-appearance:none;background-color:transparent;border:0 solid #fff;height:20px;width:300px}input.vis-configuration.vis-config-range::-webkit-slider-runnable-track{background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(180deg,#dedede 0,#c8c8c8 99%);border:1px solid #999;border-radius:3px;box-shadow:0 0 3px 0 #aaa;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#dedede",endColorstr="#c8c8c8",GradientType=0);height:5px;width:300px}input.vis-configuration.vis-config-range::-webkit-slider-thumb{-webkit-appearance:none;background:#3876c2;background:-moz-linear-gradient(top,#3876c2 0,#385380 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3876c2),color-stop(100%,#385380));background:-webkit-linear-gradient(top,#3876c2,#385380);background:-o-linear-gradient(top,#3876c2 0,#385380 100%);background:-ms-linear-gradient(top,#3876c2 0,#385380 100%);background:linear-gradient(180deg,#3876c2 0,#385380);border:1px solid #14334b;border-radius:50%;box-shadow:0 0 1px 0 #111927;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#3876c2",endColorstr="#385380",GradientType=0);height:17px;margin-top:-7px;width:17px}input.vis-configuration.vis-config-range:focus{outline:none}input.vis-configuration.vis-config-range:focus::-webkit-slider-runnable-track{background:#9d9d9d;background:-moz-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#9d9d9d),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#9d9d9d,#c8c8c8 99%);background:-o-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:linear-gradient(180deg,#9d9d9d 0,#c8c8c8 99%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#9d9d9d",endColorstr="#c8c8c8",GradientType=0)}input.vis-configuration.vis-config-range::-moz-range-track{background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(180deg,#dedede 0,#c8c8c8 99%);border:1px solid #999;border-radius:3px;box-shadow:0 0 3px 0 #aaa;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#dedede",endColorstr="#c8c8c8",GradientType=0);height:10px;width:300px}input.vis-configuration.vis-config-range::-moz-range-thumb{background:#385380;border:none;border-radius:50%;height:16px;width:16px}input.vis-configuration.vis-config-range:-moz-focusring{outline:1px solid #fff;outline-offset:-1px}input.vis-configuration.vis-config-range::-ms-track{background:transparent;border-color:transparent;border-width:6px 0;color:transparent;height:5px;width:300px}input.vis-configuration.vis-config-range::-ms-fill-lower{background:#777;border-radius:10px}input.vis-configuration.vis-config-range::-ms-fill-upper{background:#ddd;border-radius:10px}input.vis-configuration.vis-config-range::-ms-thumb{background:#385380;border:none;border-radius:50%;height:16px;width:16px}input.vis-configuration.vis-config-range:focus::-ms-fill-lower{background:#888}input.vis-configuration.vis-config-range:focus::-ms-fill-upper{background:#ccc}.vis-configuration-popup{background:rgba(57,76,89,.85);border:2px solid #f2faff;border-radius:4px;color:#fff;font-size:14px;height:30px;line-height:30px;position:absolute;text-align:center;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out;width:150px}.vis-configuration-popup:after,.vis-configuration-popup:before{border:solid transparent;content:" ";height:0;left:100%;pointer-events:none;position:absolute;top:50%;width:0}.vis-configuration-popup:after{border-color:rgba(136,183,213,0) rgba(136,183,213,0) rgba(136,183,213,0) rgba(57,76,89,.85);border-width:8px;margin-top:-8px}.vis-configuration-popup:before{border-color:rgba(194,225,245,0) rgba(194,225,245,0) rgba(194,225,245,0) #f2faff;border-width:12px;margin-top:-12px}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-horizontal{border-bottom:1px solid;height:0;position:absolute;width:100%}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-minor{border-color:#e5e5e5}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-major{border-color:#bfbfbf}.vis-data-axis .vis-y-axis.vis-major{color:#4d4d4d;position:absolute;white-space:nowrap;width:100%}.vis-data-axis .vis-y-axis.vis-major.vis-measure{border:0;margin:0;padding:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-minor{color:#bebebe;position:absolute;white-space:nowrap;width:100%}.vis-data-axis .vis-y-axis.vis-minor.vis-measure{border:0;margin:0;padding:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title{bottom:20px;color:#4d4d4d;position:absolute;text-align:center;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-title.vis-measure{margin:0;padding:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title.vis-left{bottom:0;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg);-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left bottom}.vis-data-axis .vis-y-axis.vis-title.vis-right{bottom:0;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg);-webkit-transform-origin:right bottom;-moz-transform-origin:right bottom;-ms-transform-origin:right bottom;-o-transform-origin:right bottom;transform-origin:right bottom}.vis-legend{background-color:rgba(247,252,255,.65);border:1px solid #b3b3b3;box-shadow:2px 2px 10px hsla(0,0%,60%,.55);padding:5px}.vis-legend-text{display:inline-block;white-space:nowrap} +.vis [class*=span]{min-height:0;width:auto}.vis-current-time{background-color:#ff7f6e;width:2px;z-index:1;pointer-events:none}.vis-rolling-mode-btn{height:40px;width:40px;position:absolute;top:7px;right:20px;border-radius:50%;font-size:28px;cursor:pointer;opacity:.8;color:#fff;font-weight:700;text-align:center;background:#3876c2}.vis-rolling-mode-btn:before{content:"\26F6"}.vis-rolling-mode-btn:hover{opacity:1}.vis-timeline{position:relative;border:1px solid #bfbfbf;overflow:hidden;padding:0;margin:0;box-sizing:border-box}.vis-loading-screen{width:100%;height:100%;position:absolute;top:0;left:0}.vis-panel{position:absolute;padding:0;margin:0;box-sizing:border-box}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right,.vis-panel.vis-top{border:1px #bfbfbf}.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right{border-top-style:solid;border-bottom-style:solid;overflow:hidden}.vis-left.vis-panel.vis-vertical-scroll,.vis-right.vis-panel.vis-vertical-scroll{height:100%;overflow-x:hidden;overflow-y:scroll}.vis-left.vis-panel.vis-vertical-scroll{direction:rtl}.vis-left.vis-panel.vis-vertical-scroll .vis-content{direction:ltr}.vis-right.vis-panel.vis-vertical-scroll{direction:ltr}.vis-right.vis-panel.vis-vertical-scroll .vis-content{direction:rtl}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-top{border-left-style:solid;border-right-style:solid}.vis-background{overflow:hidden}.vis-panel>.vis-content{position:relative}.vis-panel .vis-shadow{position:absolute;width:100%;height:1px;box-shadow:0 0 10px rgba(0,0,0,.8)}.vis-panel .vis-shadow.vis-top{top:-1px;left:0}.vis-panel .vis-shadow.vis-bottom{bottom:-1px;left:0}.vis-graph-group0{fill:#4f81bd;fill-opacity:0;stroke-width:2px;stroke:#4f81bd}.vis-graph-group1{fill:#f79646;fill-opacity:0;stroke-width:2px;stroke:#f79646}.vis-graph-group2{fill:#8c51cf;fill-opacity:0;stroke-width:2px;stroke:#8c51cf}.vis-graph-group3{fill:#75c841;fill-opacity:0;stroke-width:2px;stroke:#75c841}.vis-graph-group4{fill:#ff0100;fill-opacity:0;stroke-width:2px;stroke:#ff0100}.vis-graph-group5{fill:#37d8e6;fill-opacity:0;stroke-width:2px;stroke:#37d8e6}.vis-graph-group6{fill:#042662;fill-opacity:0;stroke-width:2px;stroke:#042662}.vis-graph-group7{fill:#00ff26;fill-opacity:0;stroke-width:2px;stroke:#00ff26}.vis-graph-group8{fill:#f0f;fill-opacity:0;stroke-width:2px;stroke:#f0f}.vis-graph-group9{fill:#8f3938;fill-opacity:0;stroke-width:2px;stroke:#8f3938}.vis-timeline .vis-fill{fill-opacity:.1;stroke:none}.vis-timeline .vis-bar{fill-opacity:.5;stroke-width:1px}.vis-timeline .vis-point{stroke-width:2px;fill-opacity:1}.vis-timeline .vis-legend-background{stroke-width:1px;fill-opacity:.9;fill:#fff;stroke:#c2c2c2}.vis-timeline .vis-outline{stroke-width:1px;fill-opacity:1;fill:#fff;stroke:#e5e5e5}.vis-timeline .vis-icon-fill{fill-opacity:.3;stroke:none}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-horizontal{position:absolute;width:100%;height:0;border-bottom:1px solid}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-minor{border-color:#e5e5e5}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-major{border-color:#bfbfbf}.vis-data-axis .vis-y-axis.vis-major{width:100%;position:absolute;color:#4d4d4d;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-major.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-minor{position:absolute;width:100%;color:#bebebe;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-minor.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title{position:absolute;color:#4d4d4d;white-space:nowrap;bottom:20px;text-align:center}.vis-data-axis .vis-y-axis.vis-title.vis-measure{padding:0;margin:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title.vis-left{bottom:0;-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left bottom;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}.vis-data-axis .vis-y-axis.vis-title.vis-right{bottom:0;-webkit-transform-origin:right bottom;-moz-transform-origin:right bottom;-ms-transform-origin:right bottom;-o-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.vis-legend{background-color:rgba(247,252,255,.65);padding:5px;border:1px solid #b3b3b3;box-shadow:2px 2px 10px rgba(154,154,154,.55)}.vis-legend-text{white-space:nowrap;display:inline-block}.vis-itemset{position:relative;padding:0;margin:0;box-sizing:border-box}.vis-itemset .vis-background,.vis-itemset .vis-foreground{position:absolute;width:100%;height:100%;overflow:visible}.vis-axis{position:absolute;width:100%;height:0;left:0;z-index:1}.vis-foreground .vis-group{position:relative;box-sizing:border-box;border-bottom:1px solid #bfbfbf}.vis-foreground .vis-group:last-child{border-bottom:none}.vis-nesting-group{cursor:pointer}.vis-label.vis-nested-group.vis-group-level-unknown-but-gte1{background:#f5f5f5}.vis-label.vis-nested-group.vis-group-level-0{background-color:#fff}.vis-ltr .vis-label.vis-nested-group.vis-group-level-0 .vis-inner{padding-left:0}.vis-rtl .vis-label.vis-nested-group.vis-group-level-0 .vis-inner{padding-right:0}.vis-label.vis-nested-group.vis-group-level-1{background-color:rgba(0,0,0,.05)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-1 .vis-inner{padding-left:15px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-1 .vis-inner{padding-right:15px}.vis-label.vis-nested-group.vis-group-level-2{background-color:rgba(0,0,0,.1)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-2 .vis-inner{padding-left:30px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-2 .vis-inner{padding-right:30px}.vis-label.vis-nested-group.vis-group-level-3{background-color:rgba(0,0,0,.15)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-3 .vis-inner{padding-left:45px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-3 .vis-inner{padding-right:45px}.vis-label.vis-nested-group.vis-group-level-4{background-color:rgba(0,0,0,.2)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-4 .vis-inner{padding-left:60px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-4 .vis-inner{padding-right:60px}.vis-label.vis-nested-group.vis-group-level-5{background-color:rgba(0,0,0,.25)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-5 .vis-inner{padding-left:75px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-5 .vis-inner{padding-right:75px}.vis-label.vis-nested-group.vis-group-level-6{background-color:rgba(0,0,0,.3)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-6 .vis-inner{padding-left:90px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-6 .vis-inner{padding-right:90px}.vis-label.vis-nested-group.vis-group-level-7{background-color:rgba(0,0,0,.35)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-7 .vis-inner{padding-left:105px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-7 .vis-inner{padding-right:105px}.vis-label.vis-nested-group.vis-group-level-8{background-color:rgba(0,0,0,.4)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-8 .vis-inner{padding-left:120px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-8 .vis-inner{padding-right:120px}.vis-label.vis-nested-group.vis-group-level-9{background-color:rgba(0,0,0,.45)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-9 .vis-inner{padding-left:135px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-9 .vis-inner{padding-right:135px}.vis-label.vis-nested-group{background-color:rgba(0,0,0,.5)}.vis-ltr .vis-label.vis-nested-group .vis-inner{padding-left:150px}.vis-rtl .vis-label.vis-nested-group .vis-inner{padding-right:150px}.vis-group-level-unknown-but-gte1{border:1px solid red}.vis-label.vis-nesting-group:before{display:inline-block;width:15px}.vis-label.vis-nesting-group.expanded:before{content:"\25BC"}.vis-label.vis-nesting-group.collapsed:before{content:"\25B6"}.vis-rtl .vis-label.vis-nesting-group.collapsed:before{content:"\25C0"}.vis-ltr .vis-label:not(.vis-nesting-group):not(.vis-group-level-0){padding-left:15px}.vis-rtl .vis-label:not(.vis-nesting-group):not(.vis-group-level-0){padding-right:15px}.vis-overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-labelset{position:relative;overflow:hidden;box-sizing:border-box}.vis-labelset .vis-label{position:relative;left:0;top:0;width:100%;color:#4d4d4d;box-sizing:border-box}.vis-labelset .vis-label{border-bottom:1px solid #bfbfbf}.vis-labelset .vis-label.draggable{cursor:pointer}.vis-group-is-dragging{background:rgba(0,0,0,.1)}.vis-labelset .vis-label:last-child{border-bottom:none}.vis-labelset .vis-label .vis-inner{display:inline-block;padding:5px}.vis-labelset .vis-label .vis-inner.vis-hidden{padding:0}.vis-time-axis{position:relative;overflow:hidden}.vis-time-axis.vis-foreground{top:0;left:0;width:100%}.vis-time-axis.vis-background{position:absolute;top:0;left:0;width:100%;height:100%}.vis-time-axis .vis-text{position:absolute;color:#4d4d4d;padding:3px;overflow:hidden;box-sizing:border-box;white-space:nowrap}.vis-time-axis .vis-text.vis-measure{position:absolute;padding-left:0;padding-right:0;margin-left:0;margin-right:0;visibility:hidden}.vis-time-axis .vis-grid.vis-vertical{position:absolute;border-left:1px solid}.vis-time-axis .vis-grid.vis-vertical-rtl{position:absolute;border-right:1px solid}.vis-time-axis .vis-grid.vis-minor{border-color:#e5e5e5}.vis-time-axis .vis-grid.vis-major{border-color:#bfbfbf}.vis-custom-time{background-color:#6e94ff;width:2px;cursor:move;z-index:1}.vis-custom-time>.vis-custom-time-marker{background-color:inherit;color:#fff;font-size:12px;white-space:nowrap;padding:3px 5px;top:0;cursor:initial;z-index:inherit}.vis-item{position:absolute;color:#1a1a1a;border-color:#97b0f8;border-width:1px;background-color:#d5ddf6;display:inline-block;z-index:1}.vis-item.vis-selected{border-color:#ffc200;background-color:#fff785;z-index:2}.vis-editable.vis-selected{cursor:move}.vis-item.vis-point.vis-selected{background-color:#fff785}.vis-item.vis-box{text-align:center;border-style:solid;border-radius:2px}.vis-item.vis-point{background:0 0}.vis-item.vis-dot{position:absolute;padding:0;border-width:4px;border-style:solid;border-radius:4px}.vis-item.vis-range{border-style:solid;border-radius:2px;box-sizing:border-box}.vis-item.vis-background{border:none;background-color:rgba(213,221,246,.4);box-sizing:border-box;padding:0;margin:0}.vis-item .vis-item-overflow{position:relative;width:100%;height:100%;padding:0;margin:0;overflow:hidden}.vis-item-visible-frame{white-space:nowrap}.vis-item.vis-range .vis-item-content{position:relative;display:inline-block}.vis-item.vis-background .vis-item-content{position:absolute;display:inline-block}.vis-item.vis-line{padding:0;position:absolute;width:0;border-left-width:1px;border-left-style:solid}.vis-item .vis-item-content{white-space:nowrap;box-sizing:border-box;padding:5px}.vis-item .vis-onUpdateTime-tooltip{position:absolute;background:#4f81bd;color:#fff;width:200px;text-align:center;white-space:nowrap;padding:5px;border-radius:1px;transition:.4s;-o-transition:.4s;-moz-transition:.4s;-webkit-transition:.4s}.vis-item .vis-delete,.vis-item .vis-delete-rtl{position:absolute;top:0;width:24px;height:24px;box-sizing:border-box;padding:0 5px;cursor:pointer;-webkit-transition:background .2s linear;-moz-transition:background .2s linear;-ms-transition:background .2s linear;-o-transition:background .2s linear;transition:background .2s linear}.vis-item .vis-delete{right:-24px}.vis-item .vis-delete-rtl{left:-24px}.vis-item .vis-delete-rtl:after,.vis-item .vis-delete:after{content:"\00D7";color:red;font-family:arial,sans-serif;font-size:22px;font-weight:700;-webkit-transition:color .2s linear;-moz-transition:color .2s linear;-ms-transition:color .2s linear;-o-transition:color .2s linear;transition:color .2s linear}.vis-item .vis-delete-rtl:hover,.vis-item .vis-delete:hover{background:red}.vis-item .vis-delete-rtl:hover:after,.vis-item .vis-delete:hover:after{color:#fff}.vis-item .vis-drag-center{position:absolute;width:100%;height:100%;top:0;left:0;cursor:move}.vis-item.vis-range .vis-drag-left{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0;left:-4px;cursor:w-resize}.vis-item.vis-range .vis-drag-right{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0;right:-4px;cursor:e-resize}.vis-range.vis-item.vis-readonly .vis-drag-left,.vis-range.vis-item.vis-readonly .vis-drag-right{cursor:auto}.vis-item.vis-cluster{vertical-align:center;text-align:center;border-style:solid;border-radius:2px}.vis-item.vis-cluster-line{padding:0;position:absolute;width:0;border-left-width:1px;border-left-style:solid}.vis-item.vis-cluster-dot{position:absolute;padding:0;border-width:4px;border-style:solid;border-radius:4px}.vis .overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-active{box-shadow:0 0 10px #86d5f8}div.vis-configuration{position:relative;display:block;float:left;font-size:12px}div.vis-configuration-wrapper{display:block;width:700px}div.vis-configuration-wrapper::after{clear:both;content:"";display:block}div.vis-configuration.vis-config-option-container{display:block;width:495px;background-color:#fff;border:2px solid #f7f8fa;border-radius:4px;margin-top:20px;left:10px;padding-left:5px}div.vis-configuration.vis-config-button{display:block;width:495px;height:25px;vertical-align:middle;line-height:25px;background-color:#f7f8fa;border:2px solid #ceced0;border-radius:4px;margin-top:20px;left:10px;padding-left:5px;cursor:pointer;margin-bottom:30px}div.vis-configuration.vis-config-button.hover{background-color:#4588e6;border:2px solid #214373;color:#fff}div.vis-configuration.vis-config-item{display:block;float:left;width:495px;height:25px;vertical-align:middle;line-height:25px}div.vis-configuration.vis-config-item.vis-config-s2{left:10px;background-color:#f7f8fa;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s3{left:20px;background-color:#e4e9f0;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s4{left:30px;background-color:#cfd8e6;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-header{font-size:18px;font-weight:700}div.vis-configuration.vis-config-label{width:120px;height:25px;line-height:25px}div.vis-configuration.vis-config-label.vis-config-s3{width:110px}div.vis-configuration.vis-config-label.vis-config-s4{width:100px}div.vis-configuration.vis-config-colorBlock{top:1px;width:30px;height:19px;border:1px solid #444;border-radius:2px;padding:0;margin:0;cursor:pointer}input.vis-configuration.vis-config-checkbox{left:-5px}input.vis-configuration.vis-config-rangeinput{position:relative;top:-5px;width:60px;padding:1px;margin:0;pointer-events:none}input.vis-configuration.vis-config-range{-webkit-appearance:none;border:0 solid #fff;background-color:rgba(0,0,0,0);width:300px;height:20px}input.vis-configuration.vis-config-range::-webkit-slider-runnable-track{width:300px;height:5px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-webkit-slider-thumb{-webkit-appearance:none;border:1px solid #14334b;height:17px;width:17px;border-radius:50%;background:#3876c2;background:-moz-linear-gradient(top,#3876c2 0,#385380 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3876c2),color-stop(100%,#385380));background:-webkit-linear-gradient(top,#3876c2 0,#385380 100%);background:-o-linear-gradient(top,#3876c2 0,#385380 100%);background:-ms-linear-gradient(top,#3876c2 0,#385380 100%);background:linear-gradient(to bottom,#3876c2 0,#385380 100%);box-shadow:#111927 0 0 1px 0;margin-top:-7px}input.vis-configuration.vis-config-range:focus{outline:0}input.vis-configuration.vis-config-range:focus::-webkit-slider-runnable-track{background:#9d9d9d;background:-moz-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#9d9d9d),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-o-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:linear-gradient(to bottom,#9d9d9d 0,#c8c8c8 99%)}input.vis-configuration.vis-config-range::-moz-range-track{width:300px;height:10px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-moz-range-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:-moz-focusring{outline:1px solid #fff;outline-offset:-1px}input.vis-configuration.vis-config-range::-ms-track{width:300px;height:5px;background:0 0;border-color:transparent;border-width:6px 0;color:transparent}input.vis-configuration.vis-config-range::-ms-fill-lower{background:#777;border-radius:10px}input.vis-configuration.vis-config-range::-ms-fill-upper{background:#ddd;border-radius:10px}input.vis-configuration.vis-config-range::-ms-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:focus::-ms-fill-lower{background:#888}input.vis-configuration.vis-config-range:focus::-ms-fill-upper{background:#ccc}.vis-configuration-popup{position:absolute;background:rgba(57,76,89,.85);border:2px solid #f2faff;line-height:30px;height:30px;width:150px;text-align:center;color:#fff;font-size:14px;border-radius:4px;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out}.vis-configuration-popup:after,.vis-configuration-popup:before{left:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.vis-configuration-popup:after{border-color:rgba(136,183,213,0);border-left-color:rgba(57,76,89,.85);border-width:8px;margin-top:-8px}.vis-configuration-popup:before{border-color:rgba(194,225,245,0);border-left-color:#f2faff;border-width:12px;margin-top:-12px}div.vis-tooltip{position:absolute;visibility:hidden;padding:5px;white-space:nowrap;font-family:verdana;font-size:14px;color:#000;background-color:#f5f4ed;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;border:1px solid #808074;box-shadow:3px 3px 10px rgba(0,0,0,.2);pointer-events:none;z-index:5} \ No newline at end of file diff --git a/core/src/main/resources/org/apache/spark/ui/static/vis-timeline-graph2d.min.js b/core/src/main/resources/org/apache/spark/ui/static/vis-timeline-graph2d.min.js index 8bbf6c7412ca8..ed252b6933bf6 100644 --- a/core/src/main/resources/org/apache/spark/ui/static/vis-timeline-graph2d.min.js +++ b/core/src/main/resources/org/apache/spark/ui/static/vis-timeline-graph2d.min.js @@ -4,8 +4,8 @@ * * Create a fully customizable, interactive timeline with items and ranges. * - * @version 7.7.2 - * @date 2023-03-22T11:14:31.874Z + * @version 7.7.3 + * @date 2023-10-27T17:57:57.604Z * * @copyright (c) 2011-2017 Almende B.V, http://almende.com * @copyright (c) 2017-2019 visjs contributors, https://github.com/visjs @@ -23,24 +23,26 @@ * * vis.js may be distributed under either license. */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).vis=t.vis||{})}(this,(function(t){var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function n(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function r(t){throw new Error('Could not dynamically require "'+t+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var o,s,a={},l={get exports(){return a},set exports(t){a=t}};function h(){return o||(o=1,function(t,e){t.exports=function(){var e,i;function n(){return e.apply(null,arguments)}function o(t){e=t}function s(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function a(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function l(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function h(t){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(t).length;var e;for(e in t)if(l(t,e))return!1;return!0}function u(t){return void 0===t}function c(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function d(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function p(t,e){var i,n=[],r=t.length;for(i=0;i>>0;for(e=0;e0)for(i=0;i=0?i?"+":"":"-")+Math.pow(10,Math.max(0,r)).toString().substr(1)+n}var F=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,j=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Y={},H={};function z(t,e,i,n){var r=n;"string"==typeof n&&(r=function(){return this[n]()}),t&&(H[t]=r),e&&(H[e[0]]=function(){return R(r.apply(this,arguments),e[1],e[2])}),i&&(H[i]=function(){return this.localeData().ordinal(r.apply(this,arguments),t)})}function B(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function G(t){var e,i,n=t.match(F);for(e=0,i=n.length;e=0&&j.test(t);)t=t.replace(j,n),j.lastIndex=0,i-=1;return t}var U={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};function X(t){var e=this._longDateFormat[t],i=this._longDateFormat[t.toUpperCase()];return e||!i?e:(this._longDateFormat[t]=i.match(F).map((function(t){return"MMMM"===t||"MM"===t||"DD"===t||"dddd"===t?t.slice(1):t})).join(""),this._longDateFormat[t])}var q="Invalid date";function $(){return this._invalidDate}var Z="%d",K=/\d{1,2}/;function J(t){return this._ordinal.replace("%d",t)}var Q={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function tt(t,e,i,n){var r=this._relativeTime[i];return E(r)?r(t,e,i,n):r.replace(/%d/i,t)}function et(t,e){var i=this._relativeTime[t>0?"future":"past"];return E(i)?i(e):i.replace(/%s/i,e)}var it={};function nt(t,e){var i=t.toLowerCase();it[i]=it[i+"s"]=it[e]=t}function rt(t){return"string"==typeof t?it[t]||it[t.toLowerCase()]:void 0}function ot(t){var e,i,n={};for(i in t)l(t,i)&&(e=rt(i))&&(n[e]=t[i]);return n}var st={};function at(t,e){st[t]=e}function lt(t){var e,i=[];for(e in t)l(t,e)&&i.push({unit:e,priority:st[e]});return i.sort((function(t,e){return t.priority-e.priority})),i}function ht(t){return t%4==0&&t%100!=0||t%400==0}function ut(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function ct(t){var e=+t,i=0;return 0!==e&&isFinite(e)&&(i=ut(e)),i}function dt(t,e){return function(i){return null!=i?(ft(this,t,i),n.updateOffset(this,e),this):pt(this,t)}}function pt(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function ft(t,e,i){t.isValid()&&!isNaN(i)&&("FullYear"===e&&ht(t.year())&&1===t.month()&&29===t.date()?(i=ct(i),t._d["set"+(t._isUTC?"UTC":"")+e](i,t.month(),te(i,t.month()))):t._d["set"+(t._isUTC?"UTC":"")+e](i))}function mt(t){return E(this[t=rt(t)])?this[t]():this}function vt(t,e){if("object"==typeof t){var i,n=lt(t=ot(t)),r=n.length;for(i=0;i68?1900:2e3)};var ge=dt("FullYear",!0);function ye(){return ht(this.year())}function be(t,e,i,n,r,o,s){var a;return t<100&&t>=0?(a=new Date(t+400,e,i,n,r,o,s),isFinite(a.getFullYear())&&a.setFullYear(t)):a=new Date(t,e,i,n,r,o,s),a}function _e(t){var e,i;return t<100&&t>=0?((i=Array.prototype.slice.call(arguments))[0]=t+400,e=new Date(Date.UTC.apply(null,i)),isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t)):e=new Date(Date.UTC.apply(null,arguments)),e}function we(t,e,i){var n=7+e-i;return-(7+_e(t,0,n).getUTCDay()-e)%7+n-1}function ke(t,e,i,n,r){var o,s,a=1+7*(e-1)+(7+i-n)%7+we(t,n,r);return a<=0?s=ve(o=t-1)+a:a>ve(t)?(o=t+1,s=a-ve(t)):(o=t,s=a),{year:o,dayOfYear:s}}function xe(t,e,i){var n,r,o=we(t.year(),e,i),s=Math.floor((t.dayOfYear()-o-1)/7)+1;return s<1?n=s+De(r=t.year()-1,e,i):s>De(t.year(),e,i)?(n=s-De(t.year(),e,i),r=t.year()+1):(r=t.year(),n=s),{week:n,year:r}}function De(t,e,i){var n=we(t,e,i),r=we(t+1,e,i);return(ve(t)-n+r)/7}function Se(t){return xe(t,this._week.dow,this._week.doy).week}z("w",["ww",2],"wo","week"),z("W",["WW",2],"Wo","isoWeek"),nt("week","w"),nt("isoWeek","W"),at("week",5),at("isoWeek",5),Nt("w",xt),Nt("ww",xt,bt),Nt("W",xt),Nt("WW",xt,bt),zt(["w","ww","W","WW"],(function(t,e,i,n){e[n.substr(0,1)]=ct(t)}));var Ce={dow:0,doy:6};function Te(){return this._week.dow}function Me(){return this._week.doy}function Oe(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")}function Ee(t){var e=xe(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")}function Pe(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}function Ie(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}function Ae(t,e){return t.slice(e,7).concat(t.slice(0,e))}z("d",0,"do","day"),z("dd",0,0,(function(t){return this.localeData().weekdaysMin(this,t)})),z("ddd",0,0,(function(t){return this.localeData().weekdaysShort(this,t)})),z("dddd",0,0,(function(t){return this.localeData().weekdays(this,t)})),z("e",0,0,"weekday"),z("E",0,0,"isoWeekday"),nt("day","d"),nt("weekday","e"),nt("isoWeekday","E"),at("day",11),at("weekday",11),at("isoWeekday",11),Nt("d",xt),Nt("e",xt),Nt("E",xt),Nt("dd",(function(t,e){return e.weekdaysMinRegex(t)})),Nt("ddd",(function(t,e){return e.weekdaysShortRegex(t)})),Nt("dddd",(function(t,e){return e.weekdaysRegex(t)})),zt(["dd","ddd","dddd"],(function(t,e,i,n){var r=i._locale.weekdaysParse(t,n,i._strict);null!=r?e.d=r:g(i).invalidWeekday=t})),zt(["d","e","E"],(function(t,e,i,n){e[n]=ct(t)}));var Le="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Ne="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Re="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Fe=Lt,je=Lt,Ye=Lt;function He(t,e){var i=s(this._weekdays)?this._weekdays:this._weekdays[t&&!0!==t&&this._weekdays.isFormat.test(e)?"format":"standalone"];return!0===t?Ae(i,this._week.dow):t?i[t.day()]:i}function ze(t){return!0===t?Ae(this._weekdaysShort,this._week.dow):t?this._weekdaysShort[t.day()]:this._weekdaysShort}function Be(t){return!0===t?Ae(this._weekdaysMin,this._week.dow):t?this._weekdaysMin[t.day()]:this._weekdaysMin}function Ge(t,e,i){var n,r,o,s=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],n=0;n<7;++n)o=m([2e3,1]).day(n),this._minWeekdaysParse[n]=this.weekdaysMin(o,"").toLocaleLowerCase(),this._shortWeekdaysParse[n]=this.weekdaysShort(o,"").toLocaleLowerCase(),this._weekdaysParse[n]=this.weekdays(o,"").toLocaleLowerCase();return i?"dddd"===e?-1!==(r=Gt.call(this._weekdaysParse,s))?r:null:"ddd"===e?-1!==(r=Gt.call(this._shortWeekdaysParse,s))?r:null:-1!==(r=Gt.call(this._minWeekdaysParse,s))?r:null:"dddd"===e?-1!==(r=Gt.call(this._weekdaysParse,s))||-1!==(r=Gt.call(this._shortWeekdaysParse,s))||-1!==(r=Gt.call(this._minWeekdaysParse,s))?r:null:"ddd"===e?-1!==(r=Gt.call(this._shortWeekdaysParse,s))||-1!==(r=Gt.call(this._weekdaysParse,s))||-1!==(r=Gt.call(this._minWeekdaysParse,s))?r:null:-1!==(r=Gt.call(this._minWeekdaysParse,s))||-1!==(r=Gt.call(this._weekdaysParse,s))||-1!==(r=Gt.call(this._shortWeekdaysParse,s))?r:null}function We(t,e,i){var n,r,o;if(this._weekdaysParseExact)return Ge.call(this,t,e,i);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),n=0;n<7;n++){if(r=m([2e3,1]).day(n),i&&!this._fullWeekdaysParse[n]&&(this._fullWeekdaysParse[n]=new RegExp("^"+this.weekdays(r,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[n]=new RegExp("^"+this.weekdaysShort(r,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[n]=new RegExp("^"+this.weekdaysMin(r,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[n]||(o="^"+this.weekdays(r,"")+"|^"+this.weekdaysShort(r,"")+"|^"+this.weekdaysMin(r,""),this._weekdaysParse[n]=new RegExp(o.replace(".",""),"i")),i&&"dddd"===e&&this._fullWeekdaysParse[n].test(t))return n;if(i&&"ddd"===e&&this._shortWeekdaysParse[n].test(t))return n;if(i&&"dd"===e&&this._minWeekdaysParse[n].test(t))return n;if(!i&&this._weekdaysParse[n].test(t))return n}}function Ve(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=Pe(t,this.localeData()),this.add(t-e,"d")):e}function Ue(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")}function Xe(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=Ie(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7}function qe(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ke.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(l(this,"_weekdaysRegex")||(this._weekdaysRegex=Fe),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)}function $e(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ke.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(l(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=je),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Ze(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ke.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(l(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Ye),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Ke(){function t(t,e){return e.length-t.length}var e,i,n,r,o,s=[],a=[],l=[],h=[];for(e=0;e<7;e++)i=m([2e3,1]).day(e),n=jt(this.weekdaysMin(i,"")),r=jt(this.weekdaysShort(i,"")),o=jt(this.weekdays(i,"")),s.push(n),a.push(r),l.push(o),h.push(n),h.push(r),h.push(o);s.sort(t),a.sort(t),l.sort(t),h.sort(t),this._weekdaysRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Je(){return this.hours()%12||12}function Qe(){return this.hours()||24}function ti(t,e){z(t,0,0,(function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)}))}function ei(t,e){return e._meridiemParse}function ii(t){return"p"===(t+"").toLowerCase().charAt(0)}z("H",["HH",2],0,"hour"),z("h",["hh",2],0,Je),z("k",["kk",2],0,Qe),z("hmm",0,0,(function(){return""+Je.apply(this)+R(this.minutes(),2)})),z("hmmss",0,0,(function(){return""+Je.apply(this)+R(this.minutes(),2)+R(this.seconds(),2)})),z("Hmm",0,0,(function(){return""+this.hours()+R(this.minutes(),2)})),z("Hmmss",0,0,(function(){return""+this.hours()+R(this.minutes(),2)+R(this.seconds(),2)})),ti("a",!0),ti("A",!1),nt("hour","h"),at("hour",13),Nt("a",ei),Nt("A",ei),Nt("H",xt),Nt("h",xt),Nt("k",xt),Nt("HH",xt,bt),Nt("hh",xt,bt),Nt("kk",xt,bt),Nt("hmm",Dt),Nt("hmmss",St),Nt("Hmm",Dt),Nt("Hmmss",St),Ht(["H","HH"],Xt),Ht(["k","kk"],(function(t,e,i){var n=ct(t);e[Xt]=24===n?0:n})),Ht(["a","A"],(function(t,e,i){i._isPm=i._locale.isPM(t),i._meridiem=t})),Ht(["h","hh"],(function(t,e,i){e[Xt]=ct(t),g(i).bigHour=!0})),Ht("hmm",(function(t,e,i){var n=t.length-2;e[Xt]=ct(t.substr(0,n)),e[qt]=ct(t.substr(n)),g(i).bigHour=!0})),Ht("hmmss",(function(t,e,i){var n=t.length-4,r=t.length-2;e[Xt]=ct(t.substr(0,n)),e[qt]=ct(t.substr(n,2)),e[$t]=ct(t.substr(r)),g(i).bigHour=!0})),Ht("Hmm",(function(t,e,i){var n=t.length-2;e[Xt]=ct(t.substr(0,n)),e[qt]=ct(t.substr(n))})),Ht("Hmmss",(function(t,e,i){var n=t.length-4,r=t.length-2;e[Xt]=ct(t.substr(0,n)),e[qt]=ct(t.substr(n,2)),e[$t]=ct(t.substr(r))}));var ni=/[ap]\.?m?\.?/i,ri=dt("Hours",!0);function oi(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"}var si,ai={calendar:L,longDateFormat:U,invalidDate:q,ordinal:Z,dayOfMonthOrdinalParse:K,relativeTime:Q,months:ee,monthsShort:ie,week:Ce,weekdays:Le,weekdaysMin:Re,weekdaysShort:Ne,meridiemParse:ni},li={},hi={};function ui(t,e){var i,n=Math.min(t.length,e.length);for(i=0;i0;){if(n=fi(r.slice(0,e).join("-")))return n;if(i&&i.length>=e&&ui(r,i)>=e-1)break;e--}o++}return si}function pi(t){return null!=t.match("^[^/\\\\]*$")}function fi(e){var i=null;if(void 0===li[e]&&t&&t.exports&&pi(e))try{i=si._abbr,r("./locale/"+e),mi(i)}catch(t){li[e]=null}return li[e]}function mi(t,e){var i;return t&&((i=u(e)?yi(t):vi(t,e))?si=i:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+t+" not found. Did you forget to load it?")),si._abbr}function vi(t,e){if(null!==e){var i,n=ai;if(e.abbr=t,null!=li[t])O("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),n=li[t]._config;else if(null!=e.parentLocale)if(null!=li[e.parentLocale])n=li[e.parentLocale]._config;else{if(null==(i=fi(e.parentLocale)))return hi[e.parentLocale]||(hi[e.parentLocale]=[]),hi[e.parentLocale].push({name:t,config:e}),null;n=i._config}return li[t]=new A(I(n,e)),hi[t]&&hi[t].forEach((function(t){vi(t.name,t.config)})),mi(t),li[t]}return delete li[t],null}function gi(t,e){if(null!=e){var i,n,r=ai;null!=li[t]&&null!=li[t].parentLocale?li[t].set(I(li[t]._config,e)):(null!=(n=fi(t))&&(r=n._config),e=I(r,e),null==n&&(e.abbr=t),(i=new A(e)).parentLocale=li[t],li[t]=i),mi(t)}else null!=li[t]&&(null!=li[t].parentLocale?(li[t]=li[t].parentLocale,t===mi()&&mi(t)):null!=li[t]&&delete li[t]);return li[t]}function yi(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return si;if(!s(t)){if(e=fi(t))return e;t=[t]}return di(t)}function bi(){return T(li)}function _i(t){var e,i=t._a;return i&&-2===g(t).overflow&&(e=i[Vt]<0||i[Vt]>11?Vt:i[Ut]<1||i[Ut]>te(i[Wt],i[Vt])?Ut:i[Xt]<0||i[Xt]>24||24===i[Xt]&&(0!==i[qt]||0!==i[$t]||0!==i[Zt])?Xt:i[qt]<0||i[qt]>59?qt:i[$t]<0||i[$t]>59?$t:i[Zt]<0||i[Zt]>999?Zt:-1,g(t)._overflowDayOfYear&&(eUt)&&(e=Ut),g(t)._overflowWeeks&&-1===e&&(e=Kt),g(t)._overflowWeekday&&-1===e&&(e=Jt),g(t).overflow=e),t}var wi=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ki=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,xi=/Z|[+-]\d\d(?::?\d\d)?/,Di=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/],["YYYYMM",/\d{6}/,!1],["YYYY",/\d{4}/,!1]],Si=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Ci=/^\/?Date\((-?\d+)/i,Ti=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,Mi={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Oi(t){var e,i,n,r,o,s,a=t._i,l=wi.exec(a)||ki.exec(a),h=Di.length,u=Si.length;if(l){for(g(t).iso=!0,e=0,i=h;eve(o)||0===t._dayOfYear)&&(g(t)._overflowDayOfYear=!0),i=_e(o,0,t._dayOfYear),t._a[Vt]=i.getUTCMonth(),t._a[Ut]=i.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=s[e]=n[e];for(;e<7;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[Xt]&&0===t._a[qt]&&0===t._a[$t]&&0===t._a[Zt]&&(t._nextDay=!0,t._a[Xt]=0),t._d=(t._useUTC?_e:be).apply(null,s),r=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[Xt]=24),t._w&&void 0!==t._w.d&&t._w.d!==r&&(g(t).weekdayMismatch=!0)}}function Hi(t){var e,i,n,r,o,s,a,l,h;null!=(e=t._w).GG||null!=e.W||null!=e.E?(o=1,s=4,i=Fi(e.GG,t._a[Wt],xe($i(),1,4).year),n=Fi(e.W,1),((r=Fi(e.E,1))<1||r>7)&&(l=!0)):(o=t._locale._week.dow,s=t._locale._week.doy,h=xe($i(),o,s),i=Fi(e.gg,t._a[Wt],h.year),n=Fi(e.w,h.week),null!=e.d?((r=e.d)<0||r>6)&&(l=!0):null!=e.e?(r=e.e+o,(e.e<0||e.e>6)&&(l=!0)):r=o),n<1||n>De(i,o,s)?g(t)._overflowWeeks=!0:null!=l?g(t)._overflowWeekday=!0:(a=ke(i,n,r,o,s),t._a[Wt]=a.year,t._dayOfYear=a.dayOfYear)}function zi(t){if(t._f!==n.ISO_8601)if(t._f!==n.RFC_2822){t._a=[],g(t).empty=!0;var e,i,r,o,s,a,l,h=""+t._i,u=h.length,c=0;for(l=(r=V(t._f,t._locale).match(F)||[]).length,e=0;e0&&g(t).unusedInput.push(s),h=h.slice(h.indexOf(i)+i.length),c+=i.length),H[o]?(i?g(t).empty=!1:g(t).unusedTokens.push(o),Bt(o,i,t)):t._strict&&!i&&g(t).unusedTokens.push(o);g(t).charsLeftOver=u-c,h.length>0&&g(t).unusedInput.push(h),t._a[Xt]<=12&&!0===g(t).bigHour&&t._a[Xt]>0&&(g(t).bigHour=void 0),g(t).parsedDateParts=t._a.slice(0),g(t).meridiem=t._meridiem,t._a[Xt]=Bi(t._locale,t._a[Xt],t._meridiem),null!==(a=g(t).era)&&(t._a[Wt]=t._locale.erasConvertYear(a,t._a[Wt])),Yi(t),_i(t)}else Ni(t);else Oi(t)}function Bi(t,e,i){var n;return null==i?e:null!=t.meridiemHour?t.meridiemHour(e,i):null!=t.isPM?((n=t.isPM(i))&&e<12&&(e+=12),n||12!==e||(e=0),e):e}function Gi(t){var e,i,n,r,o,s,a=!1,l=t._f.length;if(0===l)return g(t).invalidFormat=!0,void(t._d=new Date(NaN));for(r=0;rthis?this:t:b()}));function Ji(t,e){var i,n;if(1===e.length&&s(e[0])&&(e=e[0]),!e.length)return $i();for(i=e[0],n=1;nthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function xn(){if(!u(this._isDSTShifted))return this._isDSTShifted;var t,e={};return k(e,this),(e=Ui(e))._a?(t=e._isUTC?m(e._a):$i(e._a),this._isDSTShifted=this.isValid()&&un(e._a,t.toArray())>0):this._isDSTShifted=!1,this._isDSTShifted}function Dn(){return!!this.isValid()&&!this._isUTC}function Sn(){return!!this.isValid()&&this._isUTC}function Cn(){return!!this.isValid()&&this._isUTC&&0===this._offset}n.updateOffset=function(){};var Tn=/^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,Mn=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function On(t,e){var i,n,r,o=t,s=null;return ln(t)?o={ms:t._milliseconds,d:t._days,M:t._months}:c(t)||!isNaN(+t)?(o={},e?o[e]=+t:o.milliseconds=+t):(s=Tn.exec(t))?(i="-"===s[1]?-1:1,o={y:0,d:ct(s[Ut])*i,h:ct(s[Xt])*i,m:ct(s[qt])*i,s:ct(s[$t])*i,ms:ct(hn(1e3*s[Zt]))*i}):(s=Mn.exec(t))?(i="-"===s[1]?-1:1,o={y:En(s[2],i),M:En(s[3],i),w:En(s[4],i),d:En(s[5],i),h:En(s[6],i),m:En(s[7],i),s:En(s[8],i)}):null==o?o={}:"object"==typeof o&&("from"in o||"to"in o)&&(r=In($i(o.from),$i(o.to)),(o={}).ms=r.milliseconds,o.M=r.months),n=new an(o),ln(t)&&l(t,"_locale")&&(n._locale=t._locale),ln(t)&&l(t,"_isValid")&&(n._isValid=t._isValid),n}function En(t,e){var i=t&&parseFloat(t.replace(",","."));return(isNaN(i)?0:i)*e}function Pn(t,e){var i={};return i.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(i.months,"M").isAfter(e)&&--i.months,i.milliseconds=+e-+t.clone().add(i.months,"M"),i}function In(t,e){var i;return t.isValid()&&e.isValid()?(e=fn(e,t),t.isBefore(e)?i=Pn(t,e):((i=Pn(e,t)).milliseconds=-i.milliseconds,i.months=-i.months),i):{milliseconds:0,months:0}}function An(t,e){return function(i,n){var r;return null===n||isNaN(+n)||(O(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),r=i,i=n,n=r),Ln(this,On(i,n),t),this}}function Ln(t,e,i,r){var o=e._milliseconds,s=hn(e._days),a=hn(e._months);t.isValid()&&(r=null==r||r,a&&ue(t,pt(t,"Month")+a*i),s&&ft(t,"Date",pt(t,"Date")+s*i),o&&t._d.setTime(t._d.valueOf()+o*i),r&&n.updateOffset(t,s||a))}On.fn=an.prototype,On.invalid=sn;var Nn=An(1,"add"),Rn=An(-1,"subtract");function Fn(t){return"string"==typeof t||t instanceof String}function jn(t){return D(t)||d(t)||Fn(t)||c(t)||Hn(t)||Yn(t)||null==t}function Yn(t){var e,i,n=a(t)&&!h(t),r=!1,o=["years","year","y","months","month","M","days","day","d","dates","date","D","hours","hour","h","minutes","minute","m","seconds","second","s","milliseconds","millisecond","ms"],s=o.length;for(e=0;ei.valueOf():i.valueOf()9999?W(i,e?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):E(Date.prototype.toISOString)?e?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",W(i,"Z")):W(i,e?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")}function er(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t,e,i,n,r="moment",o="";return this.isLocal()||(r=0===this.utcOffset()?"moment.utc":"moment.parseZone",o="Z"),t="["+r+'("]',e=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i="-MM-DD[T]HH:mm:ss.SSS",n=o+'[")]',this.format(t+e+i+n)}function ir(t){t||(t=this.isUtc()?n.defaultFormatUtc:n.defaultFormat);var e=W(this,t);return this.localeData().postformat(e)}function nr(t,e){return this.isValid()&&(D(t)&&t.isValid()||$i(t).isValid())?On({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function rr(t){return this.from($i(),t)}function or(t,e){return this.isValid()&&(D(t)&&t.isValid()||$i(t).isValid())?On({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function sr(t){return this.to($i(),t)}function ar(t){var e;return void 0===t?this._locale._abbr:(null!=(e=yi(t))&&(this._locale=e),this)}n.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",n.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var lr=C("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",(function(t){return void 0===t?this.localeData():this.locale(t)}));function hr(){return this._locale}var ur=1e3,cr=60*ur,dr=60*cr,pr=3506328*dr;function fr(t,e){return(t%e+e)%e}function mr(t,e,i){return t<100&&t>=0?new Date(t+400,e,i)-pr:new Date(t,e,i).valueOf()}function vr(t,e,i){return t<100&&t>=0?Date.UTC(t+400,e,i)-pr:Date.UTC(t,e,i)}function gr(t){var e,i;if(void 0===(t=rt(t))||"millisecond"===t||!this.isValid())return this;switch(i=this._isUTC?vr:mr,t){case"year":e=i(this.year(),0,1);break;case"quarter":e=i(this.year(),this.month()-this.month()%3,1);break;case"month":e=i(this.year(),this.month(),1);break;case"week":e=i(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":e=i(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":e=i(this.year(),this.month(),this.date());break;case"hour":e=this._d.valueOf(),e-=fr(e+(this._isUTC?0:this.utcOffset()*cr),dr);break;case"minute":e=this._d.valueOf(),e-=fr(e,cr);break;case"second":e=this._d.valueOf(),e-=fr(e,ur)}return this._d.setTime(e),n.updateOffset(this,!0),this}function yr(t){var e,i;if(void 0===(t=rt(t))||"millisecond"===t||!this.isValid())return this;switch(i=this._isUTC?vr:mr,t){case"year":e=i(this.year()+1,0,1)-1;break;case"quarter":e=i(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":e=i(this.year(),this.month()+1,1)-1;break;case"week":e=i(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":e=i(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":e=i(this.year(),this.month(),this.date()+1)-1;break;case"hour":e=this._d.valueOf(),e+=dr-fr(e+(this._isUTC?0:this.utcOffset()*cr),dr)-1;break;case"minute":e=this._d.valueOf(),e+=cr-fr(e,cr)-1;break;case"second":e=this._d.valueOf(),e+=ur-fr(e,ur)-1}return this._d.setTime(e),n.updateOffset(this,!0),this}function br(){return this._d.valueOf()-6e4*(this._offset||0)}function _r(){return Math.floor(this.valueOf()/1e3)}function wr(){return new Date(this.valueOf())}function kr(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]}function xr(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}}function Dr(){return this.isValid()?this.toISOString():null}function Sr(){return y(this)}function Cr(){return f({},g(this))}function Tr(){return g(this).overflow}function Mr(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Or(t,e){var i,r,o,s=this._eras||yi("en")._eras;for(i=0,r=s.length;i=0)return l[n]}function Pr(t,e){var i=t.since<=t.until?1:-1;return void 0===e?n(t.since).year():n(t.since).year()+(e-t.offset)*i}function Ir(){var t,e,i,n=this.localeData().eras();for(t=0,e=n.length;t(o=De(t,n,r))&&(e=o),Jr.call(this,t,e,i,n,r))}function Jr(t,e,i,n,r){var o=ke(t,e,i,n,r),s=_e(o.year,0,o.dayOfYear);return this.year(s.getUTCFullYear()),this.month(s.getUTCMonth()),this.date(s.getUTCDate()),this}function Qr(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)}z("N",0,0,"eraAbbr"),z("NN",0,0,"eraAbbr"),z("NNN",0,0,"eraAbbr"),z("NNNN",0,0,"eraName"),z("NNNNN",0,0,"eraNarrow"),z("y",["y",1],"yo","eraYear"),z("y",["yy",2],0,"eraYear"),z("y",["yyy",3],0,"eraYear"),z("y",["yyyy",4],0,"eraYear"),Nt("N",Yr),Nt("NN",Yr),Nt("NNN",Yr),Nt("NNNN",Hr),Nt("NNNNN",zr),Ht(["N","NN","NNN","NNNN","NNNNN"],(function(t,e,i,n){var r=i._locale.erasParse(t,n,i._strict);r?g(i).era=r:g(i).invalidEra=t})),Nt("y",Ot),Nt("yy",Ot),Nt("yyy",Ot),Nt("yyyy",Ot),Nt("yo",Br),Ht(["y","yy","yyy","yyyy"],Wt),Ht(["yo"],(function(t,e,i,n){var r;i._locale._eraYearOrdinalRegex&&(r=t.match(i._locale._eraYearOrdinalRegex)),i._locale.eraYearOrdinalParse?e[Wt]=i._locale.eraYearOrdinalParse(t,r):e[Wt]=parseInt(t,10)})),z(0,["gg",2],0,(function(){return this.weekYear()%100})),z(0,["GG",2],0,(function(){return this.isoWeekYear()%100})),Wr("gggg","weekYear"),Wr("ggggg","weekYear"),Wr("GGGG","isoWeekYear"),Wr("GGGGG","isoWeekYear"),nt("weekYear","gg"),nt("isoWeekYear","GG"),at("weekYear",1),at("isoWeekYear",1),Nt("G",Et),Nt("g",Et),Nt("GG",xt,bt),Nt("gg",xt,bt),Nt("GGGG",Tt,wt),Nt("gggg",Tt,wt),Nt("GGGGG",Mt,kt),Nt("ggggg",Mt,kt),zt(["gggg","ggggg","GGGG","GGGGG"],(function(t,e,i,n){e[n.substr(0,2)]=ct(t)})),zt(["gg","GG"],(function(t,e,i,r){e[r]=n.parseTwoDigitYear(t)})),z("Q",0,"Qo","quarter"),nt("quarter","Q"),at("quarter",7),Nt("Q",yt),Ht("Q",(function(t,e){e[Vt]=3*(ct(t)-1)})),z("D",["DD",2],"Do","date"),nt("date","D"),at("date",9),Nt("D",xt),Nt("DD",xt,bt),Nt("Do",(function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient})),Ht(["D","DD"],Ut),Ht("Do",(function(t,e){e[Ut]=ct(t.match(xt)[0])}));var to=dt("Date",!0);function eo(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")}z("DDD",["DDDD",3],"DDDo","dayOfYear"),nt("dayOfYear","DDD"),at("dayOfYear",4),Nt("DDD",Ct),Nt("DDDD",_t),Ht(["DDD","DDDD"],(function(t,e,i){i._dayOfYear=ct(t)})),z("m",["mm",2],0,"minute"),nt("minute","m"),at("minute",14),Nt("m",xt),Nt("mm",xt,bt),Ht(["m","mm"],qt);var io=dt("Minutes",!1);z("s",["ss",2],0,"second"),nt("second","s"),at("second",15),Nt("s",xt),Nt("ss",xt,bt),Ht(["s","ss"],$t);var no,ro,oo=dt("Seconds",!1);for(z("S",0,0,(function(){return~~(this.millisecond()/100)})),z(0,["SS",2],0,(function(){return~~(this.millisecond()/10)})),z(0,["SSS",3],0,"millisecond"),z(0,["SSSS",4],0,(function(){return 10*this.millisecond()})),z(0,["SSSSS",5],0,(function(){return 100*this.millisecond()})),z(0,["SSSSSS",6],0,(function(){return 1e3*this.millisecond()})),z(0,["SSSSSSS",7],0,(function(){return 1e4*this.millisecond()})),z(0,["SSSSSSSS",8],0,(function(){return 1e5*this.millisecond()})),z(0,["SSSSSSSSS",9],0,(function(){return 1e6*this.millisecond()})),nt("millisecond","ms"),at("millisecond",16),Nt("S",Ct,yt),Nt("SS",Ct,bt),Nt("SSS",Ct,_t),no="SSSS";no.length<=9;no+="S")Nt(no,Ot);function so(t,e){e[Zt]=ct(1e3*("0."+t))}for(no="S";no.length<=9;no+="S")Ht(no,so);function ao(){return this._isUTC?"UTC":""}function lo(){return this._isUTC?"Coordinated Universal Time":""}ro=dt("Milliseconds",!1),z("z",0,0,"zoneAbbr"),z("zz",0,0,"zoneName");var ho=x.prototype;function uo(t){return $i(1e3*t)}function co(){return $i.apply(null,arguments).parseZone()}function po(t){return t}ho.add=Nn,ho.calendar=Gn,ho.clone=Wn,ho.diff=Kn,ho.endOf=yr,ho.format=ir,ho.from=nr,ho.fromNow=rr,ho.to=or,ho.toNow=sr,ho.get=mt,ho.invalidAt=Tr,ho.isAfter=Vn,ho.isBefore=Un,ho.isBetween=Xn,ho.isSame=qn,ho.isSameOrAfter=$n,ho.isSameOrBefore=Zn,ho.isValid=Sr,ho.lang=lr,ho.locale=ar,ho.localeData=hr,ho.max=Ki,ho.min=Zi,ho.parsingFlags=Cr,ho.set=vt,ho.startOf=gr,ho.subtract=Rn,ho.toArray=kr,ho.toObject=xr,ho.toDate=wr,ho.toISOString=tr,ho.inspect=er,"undefined"!=typeof Symbol&&null!=Symbol.for&&(ho[Symbol.for("nodejs.util.inspect.custom")]=function(){return"Moment<"+this.format()+">"}),ho.toJSON=Dr,ho.toString=Qn,ho.unix=_r,ho.valueOf=br,ho.creationData=Mr,ho.eraName=Ir,ho.eraNarrow=Ar,ho.eraAbbr=Lr,ho.eraYear=Nr,ho.year=ge,ho.isLeapYear=ye,ho.weekYear=Vr,ho.isoWeekYear=Ur,ho.quarter=ho.quarters=Qr,ho.month=ce,ho.daysInMonth=de,ho.week=ho.weeks=Oe,ho.isoWeek=ho.isoWeeks=Ee,ho.weeksInYear=$r,ho.weeksInWeekYear=Zr,ho.isoWeeksInYear=Xr,ho.isoWeeksInISOWeekYear=qr,ho.date=to,ho.day=ho.days=Ve,ho.weekday=Ue,ho.isoWeekday=Xe,ho.dayOfYear=eo,ho.hour=ho.hours=ri,ho.minute=ho.minutes=io,ho.second=ho.seconds=oo,ho.millisecond=ho.milliseconds=ro,ho.utcOffset=vn,ho.utc=yn,ho.local=bn,ho.parseZone=_n,ho.hasAlignedHourOffset=wn,ho.isDST=kn,ho.isLocal=Dn,ho.isUtcOffset=Sn,ho.isUtc=Cn,ho.isUTC=Cn,ho.zoneAbbr=ao,ho.zoneName=lo,ho.dates=C("dates accessor is deprecated. Use date instead.",to),ho.months=C("months accessor is deprecated. Use month instead",ce),ho.years=C("years accessor is deprecated. Use year instead",ge),ho.zone=C("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",gn),ho.isDSTShifted=C("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",xn);var fo=A.prototype;function mo(t,e,i,n){var r=yi(),o=m().set(n,e);return r[i](o,t)}function vo(t,e,i){if(c(t)&&(e=t,t=void 0),t=t||"",null!=e)return mo(t,e,i,"month");var n,r=[];for(n=0;n<12;n++)r[n]=mo(t,n,i,"month");return r}function go(t,e,i,n){"boolean"==typeof t?(c(e)&&(i=e,e=void 0),e=e||""):(i=e=t,t=!1,c(e)&&(i=e,e=void 0),e=e||"");var r,o=yi(),s=t?o._week.dow:0,a=[];if(null!=i)return mo(e,(i+s)%7,n,"day");for(r=0;r<7;r++)a[r]=mo(e,(r+s)%7,n,"day");return a}function yo(t,e){return vo(t,e,"months")}function bo(t,e){return vo(t,e,"monthsShort")}function _o(t,e,i){return go(t,e,i,"weekdays")}function wo(t,e,i){return go(t,e,i,"weekdaysShort")}function ko(t,e,i){return go(t,e,i,"weekdaysMin")}fo.calendar=N,fo.longDateFormat=X,fo.invalidDate=$,fo.ordinal=J,fo.preparse=po,fo.postformat=po,fo.relativeTime=tt,fo.pastFuture=et,fo.set=P,fo.eras=Or,fo.erasParse=Er,fo.erasConvertYear=Pr,fo.erasAbbrRegex=Fr,fo.erasNameRegex=Rr,fo.erasNarrowRegex=jr,fo.months=se,fo.monthsShort=ae,fo.monthsParse=he,fo.monthsRegex=fe,fo.monthsShortRegex=pe,fo.week=Se,fo.firstDayOfYear=Me,fo.firstDayOfWeek=Te,fo.weekdays=He,fo.weekdaysMin=Be,fo.weekdaysShort=ze,fo.weekdaysParse=We,fo.weekdaysRegex=qe,fo.weekdaysShortRegex=$e,fo.weekdaysMinRegex=Ze,fo.isPM=ii,fo.meridiem=oi,mi("en",{eras:[{since:"0001-01-01",until:1/0,offset:1,name:"Anno Domini",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"Before Christ",narrow:"BC",abbr:"BC"}],dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===ct(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),n.lang=C("moment.lang is deprecated. Use moment.locale instead.",mi),n.langData=C("moment.langData is deprecated. Use moment.localeData instead.",yi);var xo=Math.abs;function Do(){var t=this._data;return this._milliseconds=xo(this._milliseconds),this._days=xo(this._days),this._months=xo(this._months),t.milliseconds=xo(t.milliseconds),t.seconds=xo(t.seconds),t.minutes=xo(t.minutes),t.hours=xo(t.hours),t.months=xo(t.months),t.years=xo(t.years),this}function So(t,e,i,n){var r=On(e,i);return t._milliseconds+=n*r._milliseconds,t._days+=n*r._days,t._months+=n*r._months,t._bubble()}function Co(t,e){return So(this,t,e,1)}function To(t,e){return So(this,t,e,-1)}function Mo(t){return t<0?Math.floor(t):Math.ceil(t)}function Oo(){var t,e,i,n,r,o=this._milliseconds,s=this._days,a=this._months,l=this._data;return o>=0&&s>=0&&a>=0||o<=0&&s<=0&&a<=0||(o+=864e5*Mo(Po(a)+s),s=0,a=0),l.milliseconds=o%1e3,t=ut(o/1e3),l.seconds=t%60,e=ut(t/60),l.minutes=e%60,i=ut(e/60),l.hours=i%24,s+=ut(i/24),a+=r=ut(Eo(s)),s-=Mo(Po(r)),n=ut(a/12),a%=12,l.days=s,l.months=a,l.years=n,this}function Eo(t){return 4800*t/146097}function Po(t){return 146097*t/4800}function Io(t){if(!this.isValid())return NaN;var e,i,n=this._milliseconds;if("month"===(t=rt(t))||"quarter"===t||"year"===t)switch(e=this._days+n/864e5,i=this._months+Eo(e),t){case"month":return i;case"quarter":return i/3;case"year":return i/12}else switch(e=this._days+Math.round(Po(this._months)),t){case"week":return e/7+n/6048e5;case"day":return e+n/864e5;case"hour":return 24*e+n/36e5;case"minute":return 1440*e+n/6e4;case"second":return 86400*e+n/1e3;case"millisecond":return Math.floor(864e5*e)+n;default:throw new Error("Unknown unit "+t)}}function Ao(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*ct(this._months/12):NaN}function Lo(t){return function(){return this.as(t)}}var No=Lo("ms"),Ro=Lo("s"),Fo=Lo("m"),jo=Lo("h"),Yo=Lo("d"),Ho=Lo("w"),zo=Lo("M"),Bo=Lo("Q"),Go=Lo("y");function Wo(){return On(this)}function Vo(t){return t=rt(t),this.isValid()?this[t+"s"]():NaN}function Uo(t){return function(){return this.isValid()?this._data[t]:NaN}}var Xo=Uo("milliseconds"),qo=Uo("seconds"),$o=Uo("minutes"),Zo=Uo("hours"),Ko=Uo("days"),Jo=Uo("months"),Qo=Uo("years");function ts(){return ut(this.days()/7)}var es=Math.round,is={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function ns(t,e,i,n,r){return r.relativeTime(e||1,!!i,t,n)}function rs(t,e,i,n){var r=On(t).abs(),o=es(r.as("s")),s=es(r.as("m")),a=es(r.as("h")),l=es(r.as("d")),h=es(r.as("M")),u=es(r.as("w")),c=es(r.as("y")),d=o<=i.ss&&["s",o]||o0,d[4]=n,ns.apply(null,d)}function os(t){return void 0===t?es:"function"==typeof t&&(es=t,!0)}function ss(t,e){return void 0!==is[t]&&(void 0===e?is[t]:(is[t]=e,"s"===t&&(is.ss=e-1),!0))}function as(t,e){if(!this.isValid())return this.localeData().invalidDate();var i,n,r=!1,o=is;return"object"==typeof t&&(e=t,t=!1),"boolean"==typeof t&&(r=t),"object"==typeof e&&(o=Object.assign({},is,e),null!=e.s&&null==e.ss&&(o.ss=e.s-1)),n=rs(this,!r,o,i=this.localeData()),r&&(n=i.pastFuture(+this,n)),i.postformat(n)}var ls=Math.abs;function hs(t){return(t>0)-(t<0)||+t}function us(){if(!this.isValid())return this.localeData().invalidDate();var t,e,i,n,r,o,s,a,l=ls(this._milliseconds)/1e3,h=ls(this._days),u=ls(this._months),c=this.asSeconds();return c?(t=ut(l/60),e=ut(t/60),l%=60,t%=60,i=ut(u/12),u%=12,n=l?l.toFixed(3).replace(/\.?0+$/,""):"",r=c<0?"-":"",o=hs(this._months)!==hs(c)?"-":"",s=hs(this._days)!==hs(c)?"-":"",a=hs(this._milliseconds)!==hs(c)?"-":"",r+"P"+(i?o+i+"Y":"")+(u?o+u+"M":"")+(h?s+h+"D":"")+(e||t||l?"T":"")+(e?a+e+"H":"")+(t?a+t+"M":"")+(l?a+n+"S":"")):"P0D"}var cs=an.prototype;return cs.isValid=on,cs.abs=Do,cs.add=Co,cs.subtract=To,cs.as=Io,cs.asMilliseconds=No,cs.asSeconds=Ro,cs.asMinutes=Fo,cs.asHours=jo,cs.asDays=Yo,cs.asWeeks=Ho,cs.asMonths=zo,cs.asQuarters=Bo,cs.asYears=Go,cs.valueOf=Ao,cs._bubble=Oo,cs.clone=Wo,cs.get=Vo,cs.milliseconds=Xo,cs.seconds=qo,cs.minutes=$o,cs.hours=Zo,cs.days=Ko,cs.weeks=ts,cs.months=Jo,cs.years=Qo,cs.humanize=as,cs.toISOString=us,cs.toString=us,cs.toJSON=us,cs.locale=ar,cs.localeData=hr,cs.toIsoString=C("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",us),cs.lang=lr,z("X",0,0,"unix"),z("x",0,0,"valueOf"),Nt("x",Et),Nt("X",At),Ht("X",(function(t,e,i){i._d=new Date(1e3*parseFloat(t))})),Ht("x",(function(t,e,i){i._d=new Date(ct(t))})), +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).vis=t.vis||{})}(this,(function(t){var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function n(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function r(t){throw new Error('Could not dynamically require "'+t+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var o,s,a={exports:{}};function l(){return o||(o=1,function(t,e){t.exports=function(){var e,i;function n(){return e.apply(null,arguments)}function o(t){e=t}function s(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function a(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function l(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function h(t){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(t).length;var e;for(e in t)if(l(t,e))return!1;return!0}function u(t){return void 0===t}function d(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function c(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function p(t,e){var i,n=[],r=t.length;for(i=0;i>>0;for(e=0;e0)for(i=0;i=0?i?"+":"":"-")+Math.pow(10,Math.max(0,r)).toString().substr(1)+n}var F=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,j=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Y={},H={};function z(t,e,i,n){var r=n;"string"==typeof n&&(r=function(){return this[n]()}),t&&(H[t]=r),e&&(H[e[0]]=function(){return R(r.apply(this,arguments),e[1],e[2])}),i&&(H[i]=function(){return this.localeData().ordinal(r.apply(this,arguments),t)})}function B(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function G(t){var e,i,n=t.match(F);for(e=0,i=n.length;e=0&&j.test(t);)t=t.replace(j,n),j.lastIndex=0,i-=1;return t}var U={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};function X(t){var e=this._longDateFormat[t],i=this._longDateFormat[t.toUpperCase()];return e||!i?e:(this._longDateFormat[t]=i.match(F).map((function(t){return"MMMM"===t||"MM"===t||"DD"===t||"dddd"===t?t.slice(1):t})).join(""),this._longDateFormat[t])}var q="Invalid date";function $(){return this._invalidDate}var Z="%d",K=/\d{1,2}/;function J(t){return this._ordinal.replace("%d",t)}var Q={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function tt(t,e,i,n){var r=this._relativeTime[i];return E(r)?r(t,e,i,n):r.replace(/%d/i,t)}function et(t,e){var i=this._relativeTime[t>0?"future":"past"];return E(i)?i(e):i.replace(/%s/i,e)}var it={};function nt(t,e){var i=t.toLowerCase();it[i]=it[i+"s"]=it[e]=t}function rt(t){return"string"==typeof t?it[t]||it[t.toLowerCase()]:void 0}function ot(t){var e,i,n={};for(i in t)l(t,i)&&(e=rt(i))&&(n[e]=t[i]);return n}var st={};function at(t,e){st[t]=e}function lt(t){var e,i=[];for(e in t)l(t,e)&&i.push({unit:e,priority:st[e]});return i.sort((function(t,e){return t.priority-e.priority})),i}function ht(t){return t%4==0&&t%100!=0||t%400==0}function ut(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function dt(t){var e=+t,i=0;return 0!==e&&isFinite(e)&&(i=ut(e)),i}function ct(t,e){return function(i){return null!=i?(ft(this,t,i),n.updateOffset(this,e),this):pt(this,t)}}function pt(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function ft(t,e,i){t.isValid()&&!isNaN(i)&&("FullYear"===e&&ht(t.year())&&1===t.month()&&29===t.date()?(i=dt(i),t._d["set"+(t._isUTC?"UTC":"")+e](i,t.month(),te(i,t.month()))):t._d["set"+(t._isUTC?"UTC":"")+e](i))}function mt(t){return E(this[t=rt(t)])?this[t]():this}function vt(t,e){if("object"==typeof t){var i,n=lt(t=ot(t)),r=n.length;for(i=0;i68?1900:2e3)};var ge=ct("FullYear",!0);function ye(){return ht(this.year())}function be(t,e,i,n,r,o,s){var a;return t<100&&t>=0?(a=new Date(t+400,e,i,n,r,o,s),isFinite(a.getFullYear())&&a.setFullYear(t)):a=new Date(t,e,i,n,r,o,s),a}function _e(t){var e,i;return t<100&&t>=0?((i=Array.prototype.slice.call(arguments))[0]=t+400,e=new Date(Date.UTC.apply(null,i)),isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t)):e=new Date(Date.UTC.apply(null,arguments)),e}function we(t,e,i){var n=7+e-i;return-(7+_e(t,0,n).getUTCDay()-e)%7+n-1}function ke(t,e,i,n,r){var o,s,a=1+7*(e-1)+(7+i-n)%7+we(t,n,r);return a<=0?s=ve(o=t-1)+a:a>ve(t)?(o=t+1,s=a-ve(t)):(o=t,s=a),{year:o,dayOfYear:s}}function xe(t,e,i){var n,r,o=we(t.year(),e,i),s=Math.floor((t.dayOfYear()-o-1)/7)+1;return s<1?n=s+De(r=t.year()-1,e,i):s>De(t.year(),e,i)?(n=s-De(t.year(),e,i),r=t.year()+1):(r=t.year(),n=s),{week:n,year:r}}function De(t,e,i){var n=we(t,e,i),r=we(t+1,e,i);return(ve(t)-n+r)/7}function Se(t){return xe(t,this._week.dow,this._week.doy).week}z("w",["ww",2],"wo","week"),z("W",["WW",2],"Wo","isoWeek"),nt("week","w"),nt("isoWeek","W"),at("week",5),at("isoWeek",5),Nt("w",xt),Nt("ww",xt,bt),Nt("W",xt),Nt("WW",xt,bt),zt(["w","ww","W","WW"],(function(t,e,i,n){e[n.substr(0,1)]=dt(t)}));var Ce={dow:0,doy:6};function Te(){return this._week.dow}function Me(){return this._week.doy}function Oe(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")}function Ee(t){var e=xe(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")}function Pe(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}function Ae(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}function Ie(t,e){return t.slice(e,7).concat(t.slice(0,e))}z("d",0,"do","day"),z("dd",0,0,(function(t){return this.localeData().weekdaysMin(this,t)})),z("ddd",0,0,(function(t){return this.localeData().weekdaysShort(this,t)})),z("dddd",0,0,(function(t){return this.localeData().weekdays(this,t)})),z("e",0,0,"weekday"),z("E",0,0,"isoWeekday"),nt("day","d"),nt("weekday","e"),nt("isoWeekday","E"),at("day",11),at("weekday",11),at("isoWeekday",11),Nt("d",xt),Nt("e",xt),Nt("E",xt),Nt("dd",(function(t,e){return e.weekdaysMinRegex(t)})),Nt("ddd",(function(t,e){return e.weekdaysShortRegex(t)})),Nt("dddd",(function(t,e){return e.weekdaysRegex(t)})),zt(["dd","ddd","dddd"],(function(t,e,i,n){var r=i._locale.weekdaysParse(t,n,i._strict);null!=r?e.d=r:g(i).invalidWeekday=t})),zt(["d","e","E"],(function(t,e,i,n){e[n]=dt(t)}));var Le="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Ne="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Re="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Fe=Lt,je=Lt,Ye=Lt;function He(t,e){var i=s(this._weekdays)?this._weekdays:this._weekdays[t&&!0!==t&&this._weekdays.isFormat.test(e)?"format":"standalone"];return!0===t?Ie(i,this._week.dow):t?i[t.day()]:i}function ze(t){return!0===t?Ie(this._weekdaysShort,this._week.dow):t?this._weekdaysShort[t.day()]:this._weekdaysShort}function Be(t){return!0===t?Ie(this._weekdaysMin,this._week.dow):t?this._weekdaysMin[t.day()]:this._weekdaysMin}function Ge(t,e,i){var n,r,o,s=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],n=0;n<7;++n)o=m([2e3,1]).day(n),this._minWeekdaysParse[n]=this.weekdaysMin(o,"").toLocaleLowerCase(),this._shortWeekdaysParse[n]=this.weekdaysShort(o,"").toLocaleLowerCase(),this._weekdaysParse[n]=this.weekdays(o,"").toLocaleLowerCase();return i?"dddd"===e?-1!==(r=Gt.call(this._weekdaysParse,s))?r:null:"ddd"===e?-1!==(r=Gt.call(this._shortWeekdaysParse,s))?r:null:-1!==(r=Gt.call(this._minWeekdaysParse,s))?r:null:"dddd"===e?-1!==(r=Gt.call(this._weekdaysParse,s))||-1!==(r=Gt.call(this._shortWeekdaysParse,s))||-1!==(r=Gt.call(this._minWeekdaysParse,s))?r:null:"ddd"===e?-1!==(r=Gt.call(this._shortWeekdaysParse,s))||-1!==(r=Gt.call(this._weekdaysParse,s))||-1!==(r=Gt.call(this._minWeekdaysParse,s))?r:null:-1!==(r=Gt.call(this._minWeekdaysParse,s))||-1!==(r=Gt.call(this._weekdaysParse,s))||-1!==(r=Gt.call(this._shortWeekdaysParse,s))?r:null}function We(t,e,i){var n,r,o;if(this._weekdaysParseExact)return Ge.call(this,t,e,i);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),n=0;n<7;n++){if(r=m([2e3,1]).day(n),i&&!this._fullWeekdaysParse[n]&&(this._fullWeekdaysParse[n]=new RegExp("^"+this.weekdays(r,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[n]=new RegExp("^"+this.weekdaysShort(r,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[n]=new RegExp("^"+this.weekdaysMin(r,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[n]||(o="^"+this.weekdays(r,"")+"|^"+this.weekdaysShort(r,"")+"|^"+this.weekdaysMin(r,""),this._weekdaysParse[n]=new RegExp(o.replace(".",""),"i")),i&&"dddd"===e&&this._fullWeekdaysParse[n].test(t))return n;if(i&&"ddd"===e&&this._shortWeekdaysParse[n].test(t))return n;if(i&&"dd"===e&&this._minWeekdaysParse[n].test(t))return n;if(!i&&this._weekdaysParse[n].test(t))return n}}function Ve(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=Pe(t,this.localeData()),this.add(t-e,"d")):e}function Ue(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")}function Xe(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=Ae(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7}function qe(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ke.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(l(this,"_weekdaysRegex")||(this._weekdaysRegex=Fe),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)}function $e(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ke.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(l(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=je),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Ze(t){return this._weekdaysParseExact?(l(this,"_weekdaysRegex")||Ke.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(l(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Ye),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Ke(){function t(t,e){return e.length-t.length}var e,i,n,r,o,s=[],a=[],l=[],h=[];for(e=0;e<7;e++)i=m([2e3,1]).day(e),n=jt(this.weekdaysMin(i,"")),r=jt(this.weekdaysShort(i,"")),o=jt(this.weekdays(i,"")),s.push(n),a.push(r),l.push(o),h.push(n),h.push(r),h.push(o);s.sort(t),a.sort(t),l.sort(t),h.sort(t),this._weekdaysRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Je(){return this.hours()%12||12}function Qe(){return this.hours()||24}function ti(t,e){z(t,0,0,(function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)}))}function ei(t,e){return e._meridiemParse}function ii(t){return"p"===(t+"").toLowerCase().charAt(0)}z("H",["HH",2],0,"hour"),z("h",["hh",2],0,Je),z("k",["kk",2],0,Qe),z("hmm",0,0,(function(){return""+Je.apply(this)+R(this.minutes(),2)})),z("hmmss",0,0,(function(){return""+Je.apply(this)+R(this.minutes(),2)+R(this.seconds(),2)})),z("Hmm",0,0,(function(){return""+this.hours()+R(this.minutes(),2)})),z("Hmmss",0,0,(function(){return""+this.hours()+R(this.minutes(),2)+R(this.seconds(),2)})),ti("a",!0),ti("A",!1),nt("hour","h"),at("hour",13),Nt("a",ei),Nt("A",ei),Nt("H",xt),Nt("h",xt),Nt("k",xt),Nt("HH",xt,bt),Nt("hh",xt,bt),Nt("kk",xt,bt),Nt("hmm",Dt),Nt("hmmss",St),Nt("Hmm",Dt),Nt("Hmmss",St),Ht(["H","HH"],Xt),Ht(["k","kk"],(function(t,e,i){var n=dt(t);e[Xt]=24===n?0:n})),Ht(["a","A"],(function(t,e,i){i._isPm=i._locale.isPM(t),i._meridiem=t})),Ht(["h","hh"],(function(t,e,i){e[Xt]=dt(t),g(i).bigHour=!0})),Ht("hmm",(function(t,e,i){var n=t.length-2;e[Xt]=dt(t.substr(0,n)),e[qt]=dt(t.substr(n)),g(i).bigHour=!0})),Ht("hmmss",(function(t,e,i){var n=t.length-4,r=t.length-2;e[Xt]=dt(t.substr(0,n)),e[qt]=dt(t.substr(n,2)),e[$t]=dt(t.substr(r)),g(i).bigHour=!0})),Ht("Hmm",(function(t,e,i){var n=t.length-2;e[Xt]=dt(t.substr(0,n)),e[qt]=dt(t.substr(n))})),Ht("Hmmss",(function(t,e,i){var n=t.length-4,r=t.length-2;e[Xt]=dt(t.substr(0,n)),e[qt]=dt(t.substr(n,2)),e[$t]=dt(t.substr(r))}));var ni=/[ap]\.?m?\.?/i,ri=ct("Hours",!0);function oi(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"}var si,ai={calendar:L,longDateFormat:U,invalidDate:q,ordinal:Z,dayOfMonthOrdinalParse:K,relativeTime:Q,months:ee,monthsShort:ie,week:Ce,weekdays:Le,weekdaysMin:Re,weekdaysShort:Ne,meridiemParse:ni},li={},hi={};function ui(t,e){var i,n=Math.min(t.length,e.length);for(i=0;i0;){if(n=fi(r.slice(0,e).join("-")))return n;if(i&&i.length>=e&&ui(r,i)>=e-1)break;e--}o++}return si}function pi(t){return null!=t.match("^[^/\\\\]*$")}function fi(e){var i=null;if(void 0===li[e]&&t&&t.exports&&pi(e))try{i=si._abbr,r("./locale/"+e),mi(i)}catch(t){li[e]=null}return li[e]}function mi(t,e){var i;return t&&((i=u(e)?yi(t):vi(t,e))?si=i:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+t+" not found. Did you forget to load it?")),si._abbr}function vi(t,e){if(null!==e){var i,n=ai;if(e.abbr=t,null!=li[t])O("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),n=li[t]._config;else if(null!=e.parentLocale)if(null!=li[e.parentLocale])n=li[e.parentLocale]._config;else{if(null==(i=fi(e.parentLocale)))return hi[e.parentLocale]||(hi[e.parentLocale]=[]),hi[e.parentLocale].push({name:t,config:e}),null;n=i._config}return li[t]=new I(A(n,e)),hi[t]&&hi[t].forEach((function(t){vi(t.name,t.config)})),mi(t),li[t]}return delete li[t],null}function gi(t,e){if(null!=e){var i,n,r=ai;null!=li[t]&&null!=li[t].parentLocale?li[t].set(A(li[t]._config,e)):(null!=(n=fi(t))&&(r=n._config),e=A(r,e),null==n&&(e.abbr=t),(i=new I(e)).parentLocale=li[t],li[t]=i),mi(t)}else null!=li[t]&&(null!=li[t].parentLocale?(li[t]=li[t].parentLocale,t===mi()&&mi(t)):null!=li[t]&&delete li[t]);return li[t]}function yi(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return si;if(!s(t)){if(e=fi(t))return e;t=[t]}return ci(t)}function bi(){return T(li)}function _i(t){var e,i=t._a;return i&&-2===g(t).overflow&&(e=i[Vt]<0||i[Vt]>11?Vt:i[Ut]<1||i[Ut]>te(i[Wt],i[Vt])?Ut:i[Xt]<0||i[Xt]>24||24===i[Xt]&&(0!==i[qt]||0!==i[$t]||0!==i[Zt])?Xt:i[qt]<0||i[qt]>59?qt:i[$t]<0||i[$t]>59?$t:i[Zt]<0||i[Zt]>999?Zt:-1,g(t)._overflowDayOfYear&&(eUt)&&(e=Ut),g(t)._overflowWeeks&&-1===e&&(e=Kt),g(t)._overflowWeekday&&-1===e&&(e=Jt),g(t).overflow=e),t}var wi=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ki=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,xi=/Z|[+-]\d\d(?::?\d\d)?/,Di=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/],["YYYYMM",/\d{6}/,!1],["YYYY",/\d{4}/,!1]],Si=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Ci=/^\/?Date\((-?\d+)/i,Ti=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,Mi={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Oi(t){var e,i,n,r,o,s,a=t._i,l=wi.exec(a)||ki.exec(a),h=Di.length,u=Si.length;if(l){for(g(t).iso=!0,e=0,i=h;eve(o)||0===t._dayOfYear)&&(g(t)._overflowDayOfYear=!0),i=_e(o,0,t._dayOfYear),t._a[Vt]=i.getUTCMonth(),t._a[Ut]=i.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=s[e]=n[e];for(;e<7;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[Xt]&&0===t._a[qt]&&0===t._a[$t]&&0===t._a[Zt]&&(t._nextDay=!0,t._a[Xt]=0),t._d=(t._useUTC?_e:be).apply(null,s),r=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[Xt]=24),t._w&&void 0!==t._w.d&&t._w.d!==r&&(g(t).weekdayMismatch=!0)}}function Hi(t){var e,i,n,r,o,s,a,l,h;null!=(e=t._w).GG||null!=e.W||null!=e.E?(o=1,s=4,i=Fi(e.GG,t._a[Wt],xe($i(),1,4).year),n=Fi(e.W,1),((r=Fi(e.E,1))<1||r>7)&&(l=!0)):(o=t._locale._week.dow,s=t._locale._week.doy,h=xe($i(),o,s),i=Fi(e.gg,t._a[Wt],h.year),n=Fi(e.w,h.week),null!=e.d?((r=e.d)<0||r>6)&&(l=!0):null!=e.e?(r=e.e+o,(e.e<0||e.e>6)&&(l=!0)):r=o),n<1||n>De(i,o,s)?g(t)._overflowWeeks=!0:null!=l?g(t)._overflowWeekday=!0:(a=ke(i,n,r,o,s),t._a[Wt]=a.year,t._dayOfYear=a.dayOfYear)}function zi(t){if(t._f!==n.ISO_8601)if(t._f!==n.RFC_2822){t._a=[],g(t).empty=!0;var e,i,r,o,s,a,l,h=""+t._i,u=h.length,d=0;for(l=(r=V(t._f,t._locale).match(F)||[]).length,e=0;e0&&g(t).unusedInput.push(s),h=h.slice(h.indexOf(i)+i.length),d+=i.length),H[o]?(i?g(t).empty=!1:g(t).unusedTokens.push(o),Bt(o,i,t)):t._strict&&!i&&g(t).unusedTokens.push(o);g(t).charsLeftOver=u-d,h.length>0&&g(t).unusedInput.push(h),t._a[Xt]<=12&&!0===g(t).bigHour&&t._a[Xt]>0&&(g(t).bigHour=void 0),g(t).parsedDateParts=t._a.slice(0),g(t).meridiem=t._meridiem,t._a[Xt]=Bi(t._locale,t._a[Xt],t._meridiem),null!==(a=g(t).era)&&(t._a[Wt]=t._locale.erasConvertYear(a,t._a[Wt])),Yi(t),_i(t)}else Ni(t);else Oi(t)}function Bi(t,e,i){var n;return null==i?e:null!=t.meridiemHour?t.meridiemHour(e,i):null!=t.isPM?((n=t.isPM(i))&&e<12&&(e+=12),n||12!==e||(e=0),e):e}function Gi(t){var e,i,n,r,o,s,a=!1,l=t._f.length;if(0===l)return g(t).invalidFormat=!0,void(t._d=new Date(NaN));for(r=0;rthis?this:t:b()}));function Ji(t,e){var i,n;if(1===e.length&&s(e[0])&&(e=e[0]),!e.length)return $i();for(i=e[0],n=1;nthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function xn(){if(!u(this._isDSTShifted))return this._isDSTShifted;var t,e={};return k(e,this),(e=Ui(e))._a?(t=e._isUTC?m(e._a):$i(e._a),this._isDSTShifted=this.isValid()&&un(e._a,t.toArray())>0):this._isDSTShifted=!1,this._isDSTShifted}function Dn(){return!!this.isValid()&&!this._isUTC}function Sn(){return!!this.isValid()&&this._isUTC}function Cn(){return!!this.isValid()&&this._isUTC&&0===this._offset}n.updateOffset=function(){};var Tn=/^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,Mn=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function On(t,e){var i,n,r,o=t,s=null;return ln(t)?o={ms:t._milliseconds,d:t._days,M:t._months}:d(t)||!isNaN(+t)?(o={},e?o[e]=+t:o.milliseconds=+t):(s=Tn.exec(t))?(i="-"===s[1]?-1:1,o={y:0,d:dt(s[Ut])*i,h:dt(s[Xt])*i,m:dt(s[qt])*i,s:dt(s[$t])*i,ms:dt(hn(1e3*s[Zt]))*i}):(s=Mn.exec(t))?(i="-"===s[1]?-1:1,o={y:En(s[2],i),M:En(s[3],i),w:En(s[4],i),d:En(s[5],i),h:En(s[6],i),m:En(s[7],i),s:En(s[8],i)}):null==o?o={}:"object"==typeof o&&("from"in o||"to"in o)&&(r=An($i(o.from),$i(o.to)),(o={}).ms=r.milliseconds,o.M=r.months),n=new an(o),ln(t)&&l(t,"_locale")&&(n._locale=t._locale),ln(t)&&l(t,"_isValid")&&(n._isValid=t._isValid),n}function En(t,e){var i=t&&parseFloat(t.replace(",","."));return(isNaN(i)?0:i)*e}function Pn(t,e){var i={};return i.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(i.months,"M").isAfter(e)&&--i.months,i.milliseconds=+e-+t.clone().add(i.months,"M"),i}function An(t,e){var i;return t.isValid()&&e.isValid()?(e=fn(e,t),t.isBefore(e)?i=Pn(t,e):((i=Pn(e,t)).milliseconds=-i.milliseconds,i.months=-i.months),i):{milliseconds:0,months:0}}function In(t,e){return function(i,n){var r;return null===n||isNaN(+n)||(O(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),r=i,i=n,n=r),Ln(this,On(i,n),t),this}}function Ln(t,e,i,r){var o=e._milliseconds,s=hn(e._days),a=hn(e._months);t.isValid()&&(r=null==r||r,a&&ue(t,pt(t,"Month")+a*i),s&&ft(t,"Date",pt(t,"Date")+s*i),o&&t._d.setTime(t._d.valueOf()+o*i),r&&n.updateOffset(t,s||a))}On.fn=an.prototype,On.invalid=sn;var Nn=In(1,"add"),Rn=In(-1,"subtract");function Fn(t){return"string"==typeof t||t instanceof String}function jn(t){return D(t)||c(t)||Fn(t)||d(t)||Hn(t)||Yn(t)||null==t}function Yn(t){var e,i,n=a(t)&&!h(t),r=!1,o=["years","year","y","months","month","M","days","day","d","dates","date","D","hours","hour","h","minutes","minute","m","seconds","second","s","milliseconds","millisecond","ms"],s=o.length;for(e=0;ei.valueOf():i.valueOf()9999?W(i,e?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):E(Date.prototype.toISOString)?e?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",W(i,"Z")):W(i,e?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")}function er(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t,e,i,n,r="moment",o="";return this.isLocal()||(r=0===this.utcOffset()?"moment.utc":"moment.parseZone",o="Z"),t="["+r+'("]',e=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i="-MM-DD[T]HH:mm:ss.SSS",n=o+'[")]',this.format(t+e+i+n)}function ir(t){t||(t=this.isUtc()?n.defaultFormatUtc:n.defaultFormat);var e=W(this,t);return this.localeData().postformat(e)}function nr(t,e){return this.isValid()&&(D(t)&&t.isValid()||$i(t).isValid())?On({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function rr(t){return this.from($i(),t)}function or(t,e){return this.isValid()&&(D(t)&&t.isValid()||$i(t).isValid())?On({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function sr(t){return this.to($i(),t)}function ar(t){var e;return void 0===t?this._locale._abbr:(null!=(e=yi(t))&&(this._locale=e),this)}n.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",n.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var lr=C("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",(function(t){return void 0===t?this.localeData():this.locale(t)}));function hr(){return this._locale}var ur=1e3,dr=60*ur,cr=60*dr,pr=3506328*cr;function fr(t,e){return(t%e+e)%e}function mr(t,e,i){return t<100&&t>=0?new Date(t+400,e,i)-pr:new Date(t,e,i).valueOf()}function vr(t,e,i){return t<100&&t>=0?Date.UTC(t+400,e,i)-pr:Date.UTC(t,e,i)}function gr(t){var e,i;if(void 0===(t=rt(t))||"millisecond"===t||!this.isValid())return this;switch(i=this._isUTC?vr:mr,t){case"year":e=i(this.year(),0,1);break;case"quarter":e=i(this.year(),this.month()-this.month()%3,1);break;case"month":e=i(this.year(),this.month(),1);break;case"week":e=i(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":e=i(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":e=i(this.year(),this.month(),this.date());break;case"hour":e=this._d.valueOf(),e-=fr(e+(this._isUTC?0:this.utcOffset()*dr),cr);break;case"minute":e=this._d.valueOf(),e-=fr(e,dr);break;case"second":e=this._d.valueOf(),e-=fr(e,ur)}return this._d.setTime(e),n.updateOffset(this,!0),this}function yr(t){var e,i;if(void 0===(t=rt(t))||"millisecond"===t||!this.isValid())return this;switch(i=this._isUTC?vr:mr,t){case"year":e=i(this.year()+1,0,1)-1;break;case"quarter":e=i(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":e=i(this.year(),this.month()+1,1)-1;break;case"week":e=i(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":e=i(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":e=i(this.year(),this.month(),this.date()+1)-1;break;case"hour":e=this._d.valueOf(),e+=cr-fr(e+(this._isUTC?0:this.utcOffset()*dr),cr)-1;break;case"minute":e=this._d.valueOf(),e+=dr-fr(e,dr)-1;break;case"second":e=this._d.valueOf(),e+=ur-fr(e,ur)-1}return this._d.setTime(e),n.updateOffset(this,!0),this}function br(){return this._d.valueOf()-6e4*(this._offset||0)}function _r(){return Math.floor(this.valueOf()/1e3)}function wr(){return new Date(this.valueOf())}function kr(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]}function xr(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}}function Dr(){return this.isValid()?this.toISOString():null}function Sr(){return y(this)}function Cr(){return f({},g(this))}function Tr(){return g(this).overflow}function Mr(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Or(t,e){var i,r,o,s=this._eras||yi("en")._eras;for(i=0,r=s.length;i=0)return l[n]}function Pr(t,e){var i=t.since<=t.until?1:-1;return void 0===e?n(t.since).year():n(t.since).year()+(e-t.offset)*i}function Ar(){var t,e,i,n=this.localeData().eras();for(t=0,e=n.length;t(o=De(t,n,r))&&(e=o),Jr.call(this,t,e,i,n,r))}function Jr(t,e,i,n,r){var o=ke(t,e,i,n,r),s=_e(o.year,0,o.dayOfYear);return this.year(s.getUTCFullYear()),this.month(s.getUTCMonth()),this.date(s.getUTCDate()),this}function Qr(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)}z("N",0,0,"eraAbbr"),z("NN",0,0,"eraAbbr"),z("NNN",0,0,"eraAbbr"),z("NNNN",0,0,"eraName"),z("NNNNN",0,0,"eraNarrow"),z("y",["y",1],"yo","eraYear"),z("y",["yy",2],0,"eraYear"),z("y",["yyy",3],0,"eraYear"),z("y",["yyyy",4],0,"eraYear"),Nt("N",Yr),Nt("NN",Yr),Nt("NNN",Yr),Nt("NNNN",Hr),Nt("NNNNN",zr),Ht(["N","NN","NNN","NNNN","NNNNN"],(function(t,e,i,n){var r=i._locale.erasParse(t,n,i._strict);r?g(i).era=r:g(i).invalidEra=t})),Nt("y",Ot),Nt("yy",Ot),Nt("yyy",Ot),Nt("yyyy",Ot),Nt("yo",Br),Ht(["y","yy","yyy","yyyy"],Wt),Ht(["yo"],(function(t,e,i,n){var r;i._locale._eraYearOrdinalRegex&&(r=t.match(i._locale._eraYearOrdinalRegex)),i._locale.eraYearOrdinalParse?e[Wt]=i._locale.eraYearOrdinalParse(t,r):e[Wt]=parseInt(t,10)})),z(0,["gg",2],0,(function(){return this.weekYear()%100})),z(0,["GG",2],0,(function(){return this.isoWeekYear()%100})),Wr("gggg","weekYear"),Wr("ggggg","weekYear"),Wr("GGGG","isoWeekYear"),Wr("GGGGG","isoWeekYear"),nt("weekYear","gg"),nt("isoWeekYear","GG"),at("weekYear",1),at("isoWeekYear",1),Nt("G",Et),Nt("g",Et),Nt("GG",xt,bt),Nt("gg",xt,bt),Nt("GGGG",Tt,wt),Nt("gggg",Tt,wt),Nt("GGGGG",Mt,kt),Nt("ggggg",Mt,kt),zt(["gggg","ggggg","GGGG","GGGGG"],(function(t,e,i,n){e[n.substr(0,2)]=dt(t)})),zt(["gg","GG"],(function(t,e,i,r){e[r]=n.parseTwoDigitYear(t)})),z("Q",0,"Qo","quarter"),nt("quarter","Q"),at("quarter",7),Nt("Q",yt),Ht("Q",(function(t,e){e[Vt]=3*(dt(t)-1)})),z("D",["DD",2],"Do","date"),nt("date","D"),at("date",9),Nt("D",xt),Nt("DD",xt,bt),Nt("Do",(function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient})),Ht(["D","DD"],Ut),Ht("Do",(function(t,e){e[Ut]=dt(t.match(xt)[0])}));var to=ct("Date",!0);function eo(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")}z("DDD",["DDDD",3],"DDDo","dayOfYear"),nt("dayOfYear","DDD"),at("dayOfYear",4),Nt("DDD",Ct),Nt("DDDD",_t),Ht(["DDD","DDDD"],(function(t,e,i){i._dayOfYear=dt(t)})),z("m",["mm",2],0,"minute"),nt("minute","m"),at("minute",14),Nt("m",xt),Nt("mm",xt,bt),Ht(["m","mm"],qt);var io=ct("Minutes",!1);z("s",["ss",2],0,"second"),nt("second","s"),at("second",15),Nt("s",xt),Nt("ss",xt,bt),Ht(["s","ss"],$t);var no,ro,oo=ct("Seconds",!1);for(z("S",0,0,(function(){return~~(this.millisecond()/100)})),z(0,["SS",2],0,(function(){return~~(this.millisecond()/10)})),z(0,["SSS",3],0,"millisecond"),z(0,["SSSS",4],0,(function(){return 10*this.millisecond()})),z(0,["SSSSS",5],0,(function(){return 100*this.millisecond()})),z(0,["SSSSSS",6],0,(function(){return 1e3*this.millisecond()})),z(0,["SSSSSSS",7],0,(function(){return 1e4*this.millisecond()})),z(0,["SSSSSSSS",8],0,(function(){return 1e5*this.millisecond()})),z(0,["SSSSSSSSS",9],0,(function(){return 1e6*this.millisecond()})),nt("millisecond","ms"),at("millisecond",16),Nt("S",Ct,yt),Nt("SS",Ct,bt),Nt("SSS",Ct,_t),no="SSSS";no.length<=9;no+="S")Nt(no,Ot);function so(t,e){e[Zt]=dt(1e3*("0."+t))}for(no="S";no.length<=9;no+="S")Ht(no,so);function ao(){return this._isUTC?"UTC":""}function lo(){return this._isUTC?"Coordinated Universal Time":""}ro=ct("Milliseconds",!1),z("z",0,0,"zoneAbbr"),z("zz",0,0,"zoneName");var ho=x.prototype;function uo(t){return $i(1e3*t)}function co(){return $i.apply(null,arguments).parseZone()}function po(t){return t}ho.add=Nn,ho.calendar=Gn,ho.clone=Wn,ho.diff=Kn,ho.endOf=yr,ho.format=ir,ho.from=nr,ho.fromNow=rr,ho.to=or,ho.toNow=sr,ho.get=mt,ho.invalidAt=Tr,ho.isAfter=Vn,ho.isBefore=Un,ho.isBetween=Xn,ho.isSame=qn,ho.isSameOrAfter=$n,ho.isSameOrBefore=Zn,ho.isValid=Sr,ho.lang=lr,ho.locale=ar,ho.localeData=hr,ho.max=Ki,ho.min=Zi,ho.parsingFlags=Cr,ho.set=vt,ho.startOf=gr,ho.subtract=Rn,ho.toArray=kr,ho.toObject=xr,ho.toDate=wr,ho.toISOString=tr,ho.inspect=er,"undefined"!=typeof Symbol&&null!=Symbol.for&&(ho[Symbol.for("nodejs.util.inspect.custom")]=function(){return"Moment<"+this.format()+">"}),ho.toJSON=Dr,ho.toString=Qn,ho.unix=_r,ho.valueOf=br,ho.creationData=Mr,ho.eraName=Ar,ho.eraNarrow=Ir,ho.eraAbbr=Lr,ho.eraYear=Nr,ho.year=ge,ho.isLeapYear=ye,ho.weekYear=Vr,ho.isoWeekYear=Ur,ho.quarter=ho.quarters=Qr,ho.month=de,ho.daysInMonth=ce,ho.week=ho.weeks=Oe,ho.isoWeek=ho.isoWeeks=Ee,ho.weeksInYear=$r,ho.weeksInWeekYear=Zr,ho.isoWeeksInYear=Xr,ho.isoWeeksInISOWeekYear=qr,ho.date=to,ho.day=ho.days=Ve,ho.weekday=Ue,ho.isoWeekday=Xe,ho.dayOfYear=eo,ho.hour=ho.hours=ri,ho.minute=ho.minutes=io,ho.second=ho.seconds=oo,ho.millisecond=ho.milliseconds=ro,ho.utcOffset=vn,ho.utc=yn,ho.local=bn,ho.parseZone=_n,ho.hasAlignedHourOffset=wn,ho.isDST=kn,ho.isLocal=Dn,ho.isUtcOffset=Sn,ho.isUtc=Cn,ho.isUTC=Cn,ho.zoneAbbr=ao,ho.zoneName=lo,ho.dates=C("dates accessor is deprecated. Use date instead.",to),ho.months=C("months accessor is deprecated. Use month instead",de),ho.years=C("years accessor is deprecated. Use year instead",ge),ho.zone=C("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",gn),ho.isDSTShifted=C("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",xn);var fo=I.prototype;function mo(t,e,i,n){var r=yi(),o=m().set(n,e);return r[i](o,t)}function vo(t,e,i){if(d(t)&&(e=t,t=void 0),t=t||"",null!=e)return mo(t,e,i,"month");var n,r=[];for(n=0;n<12;n++)r[n]=mo(t,n,i,"month");return r}function go(t,e,i,n){"boolean"==typeof t?(d(e)&&(i=e,e=void 0),e=e||""):(i=e=t,t=!1,d(e)&&(i=e,e=void 0),e=e||"");var r,o=yi(),s=t?o._week.dow:0,a=[];if(null!=i)return mo(e,(i+s)%7,n,"day");for(r=0;r<7;r++)a[r]=mo(e,(r+s)%7,n,"day");return a}function yo(t,e){return vo(t,e,"months")}function bo(t,e){return vo(t,e,"monthsShort")}function _o(t,e,i){return go(t,e,i,"weekdays")}function wo(t,e,i){return go(t,e,i,"weekdaysShort")}function ko(t,e,i){return go(t,e,i,"weekdaysMin")}fo.calendar=N,fo.longDateFormat=X,fo.invalidDate=$,fo.ordinal=J,fo.preparse=po,fo.postformat=po,fo.relativeTime=tt,fo.pastFuture=et,fo.set=P,fo.eras=Or,fo.erasParse=Er,fo.erasConvertYear=Pr,fo.erasAbbrRegex=Fr,fo.erasNameRegex=Rr,fo.erasNarrowRegex=jr,fo.months=se,fo.monthsShort=ae,fo.monthsParse=he,fo.monthsRegex=fe,fo.monthsShortRegex=pe,fo.week=Se,fo.firstDayOfYear=Me,fo.firstDayOfWeek=Te,fo.weekdays=He,fo.weekdaysMin=Be,fo.weekdaysShort=ze,fo.weekdaysParse=We,fo.weekdaysRegex=qe,fo.weekdaysShortRegex=$e,fo.weekdaysMinRegex=Ze,fo.isPM=ii,fo.meridiem=oi,mi("en",{eras:[{since:"0001-01-01",until:1/0,offset:1,name:"Anno Domini",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"Before Christ",narrow:"BC",abbr:"BC"}],dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===dt(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),n.lang=C("moment.lang is deprecated. Use moment.locale instead.",mi),n.langData=C("moment.langData is deprecated. Use moment.localeData instead.",yi);var xo=Math.abs;function Do(){var t=this._data;return this._milliseconds=xo(this._milliseconds),this._days=xo(this._days),this._months=xo(this._months),t.milliseconds=xo(t.milliseconds),t.seconds=xo(t.seconds),t.minutes=xo(t.minutes),t.hours=xo(t.hours),t.months=xo(t.months),t.years=xo(t.years),this}function So(t,e,i,n){var r=On(e,i);return t._milliseconds+=n*r._milliseconds,t._days+=n*r._days,t._months+=n*r._months,t._bubble()}function Co(t,e){return So(this,t,e,1)}function To(t,e){return So(this,t,e,-1)}function Mo(t){return t<0?Math.floor(t):Math.ceil(t)}function Oo(){var t,e,i,n,r,o=this._milliseconds,s=this._days,a=this._months,l=this._data;return o>=0&&s>=0&&a>=0||o<=0&&s<=0&&a<=0||(o+=864e5*Mo(Po(a)+s),s=0,a=0),l.milliseconds=o%1e3,t=ut(o/1e3),l.seconds=t%60,e=ut(t/60),l.minutes=e%60,i=ut(e/60),l.hours=i%24,s+=ut(i/24),a+=r=ut(Eo(s)),s-=Mo(Po(r)),n=ut(a/12),a%=12,l.days=s,l.months=a,l.years=n,this}function Eo(t){return 4800*t/146097}function Po(t){return 146097*t/4800}function Ao(t){if(!this.isValid())return NaN;var e,i,n=this._milliseconds;if("month"===(t=rt(t))||"quarter"===t||"year"===t)switch(e=this._days+n/864e5,i=this._months+Eo(e),t){case"month":return i;case"quarter":return i/3;case"year":return i/12}else switch(e=this._days+Math.round(Po(this._months)),t){case"week":return e/7+n/6048e5;case"day":return e+n/864e5;case"hour":return 24*e+n/36e5;case"minute":return 1440*e+n/6e4;case"second":return 86400*e+n/1e3;case"millisecond":return Math.floor(864e5*e)+n;default:throw new Error("Unknown unit "+t)}}function Io(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*dt(this._months/12):NaN}function Lo(t){return function(){return this.as(t)}}var No=Lo("ms"),Ro=Lo("s"),Fo=Lo("m"),jo=Lo("h"),Yo=Lo("d"),Ho=Lo("w"),zo=Lo("M"),Bo=Lo("Q"),Go=Lo("y");function Wo(){return On(this)}function Vo(t){return t=rt(t),this.isValid()?this[t+"s"]():NaN}function Uo(t){return function(){return this.isValid()?this._data[t]:NaN}}var Xo=Uo("milliseconds"),qo=Uo("seconds"),$o=Uo("minutes"),Zo=Uo("hours"),Ko=Uo("days"),Jo=Uo("months"),Qo=Uo("years");function ts(){return ut(this.days()/7)}var es=Math.round,is={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function ns(t,e,i,n,r){return r.relativeTime(e||1,!!i,t,n)}function rs(t,e,i,n){var r=On(t).abs(),o=es(r.as("s")),s=es(r.as("m")),a=es(r.as("h")),l=es(r.as("d")),h=es(r.as("M")),u=es(r.as("w")),d=es(r.as("y")),c=o<=i.ss&&["s",o]||o0,c[4]=n,ns.apply(null,c)}function os(t){return void 0===t?es:"function"==typeof t&&(es=t,!0)}function ss(t,e){return void 0!==is[t]&&(void 0===e?is[t]:(is[t]=e,"s"===t&&(is.ss=e-1),!0))}function as(t,e){if(!this.isValid())return this.localeData().invalidDate();var i,n,r=!1,o=is;return"object"==typeof t&&(e=t,t=!1),"boolean"==typeof t&&(r=t),"object"==typeof e&&(o=Object.assign({},is,e),null!=e.s&&null==e.ss&&(o.ss=e.s-1)),n=rs(this,!r,o,i=this.localeData()),r&&(n=i.pastFuture(+this,n)),i.postformat(n)}var ls=Math.abs;function hs(t){return(t>0)-(t<0)||+t}function us(){if(!this.isValid())return this.localeData().invalidDate();var t,e,i,n,r,o,s,a,l=ls(this._milliseconds)/1e3,h=ls(this._days),u=ls(this._months),d=this.asSeconds();return d?(t=ut(l/60),e=ut(t/60),l%=60,t%=60,i=ut(u/12),u%=12,n=l?l.toFixed(3).replace(/\.?0+$/,""):"",r=d<0?"-":"",o=hs(this._months)!==hs(d)?"-":"",s=hs(this._days)!==hs(d)?"-":"",a=hs(this._milliseconds)!==hs(d)?"-":"",r+"P"+(i?o+i+"Y":"")+(u?o+u+"M":"")+(h?s+h+"D":"")+(e||t||l?"T":"")+(e?a+e+"H":"")+(t?a+t+"M":"")+(l?a+n+"S":"")):"P0D"}var ds=an.prototype;return ds.isValid=on,ds.abs=Do,ds.add=Co,ds.subtract=To,ds.as=Ao,ds.asMilliseconds=No,ds.asSeconds=Ro,ds.asMinutes=Fo,ds.asHours=jo,ds.asDays=Yo,ds.asWeeks=Ho,ds.asMonths=zo,ds.asQuarters=Bo,ds.asYears=Go,ds.valueOf=Io,ds._bubble=Oo,ds.clone=Wo,ds.get=Vo,ds.milliseconds=Xo,ds.seconds=qo,ds.minutes=$o,ds.hours=Zo,ds.days=Ko,ds.weeks=ts,ds.months=Jo,ds.years=Qo,ds.humanize=as,ds.toISOString=us,ds.toString=us,ds.toJSON=us,ds.locale=ar,ds.localeData=hr,ds.toIsoString=C("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",us),ds.lang=lr,z("X",0,0,"unix"),z("x",0,0,"valueOf"),Nt("x",Et),Nt("X",It),Ht("X",(function(t,e,i){i._d=new Date(1e3*parseFloat(t))})),Ht("x",(function(t,e,i){i._d=new Date(dt(t))})), //! moment.js -n.version="2.29.4",o($i),n.fn=ho,n.min=Qi,n.max=tn,n.now=en,n.utc=m,n.unix=uo,n.months=yo,n.isDate=d,n.locale=mi,n.invalid=b,n.duration=On,n.isMoment=D,n.weekdays=_o,n.parseZone=co,n.localeData=yi,n.isDuration=ln,n.monthsShort=bo,n.weekdaysMin=ko,n.defineLocale=vi,n.updateLocale=gi,n.locales=bi,n.weekdaysShort=wo,n.normalizeUnits=rt,n.relativeTimeRounding=os,n.relativeTimeThreshold=ss,n.calendarFormat=Bn,n.prototype=ho,n.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},n}()}(l)),a}s=function(t){ +n.version="2.29.4",o($i),n.fn=ho,n.min=Qi,n.max=tn,n.now=en,n.utc=m,n.unix=uo,n.months=yo,n.isDate=c,n.locale=mi,n.invalid=b,n.duration=On,n.isMoment=D,n.weekdays=_o,n.parseZone=co,n.localeData=yi,n.isDuration=ln,n.monthsShort=bo,n.weekdaysMin=ko,n.defineLocale=vi,n.updateLocale=gi,n.locales=bi,n.weekdaysShort=wo,n.normalizeUnits=rt,n.relativeTimeRounding=os,n.relativeTimeThreshold=ss,n.calendarFormat=Bn,n.prototype=ho,n.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},n}()}(a)),a.exports}s=function(t){ //! moment.js locale configuration -function e(t,e,i,n){var r={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[t+" Tage",t+" Tagen"],w:["eine Woche","einer Woche"],M:["ein Monat","einem Monat"],MM:[t+" Monate",t+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[t+" Jahre",t+" Jahren"]};return e?r[i][0]:r[i][1]}return t.defineLocale("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:e,mm:"%d Minuten",h:e,hh:"%d Stunden",d:e,dd:e,w:e,ww:"%d Wochen",M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})},s(h()),function(t,e){e(h())}(0,(function(t){ +function e(t,e,i,n){var r={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[t+" Tage",t+" Tagen"],w:["eine Woche","einer Woche"],M:["ein Monat","einem Monat"],MM:[t+" Monate",t+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[t+" Jahre",t+" Jahren"]};return e?r[i][0]:r[i][1]}return t.defineLocale("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:e,mm:"%d Minuten",h:e,hh:"%d Stunden",d:e,dd:e,w:e,ww:"%d Wochen",M:e,MM:e,y:e,yy:e},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})},s(l()),function(t,e){e(l())}(0,(function(t){ //! moment.js locale configuration -var e="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),i="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),n=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],r=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;return t.defineLocale("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(t,n){return t?/-MMM-/.test(n)?i[t.month()]:e[t.month()]:e},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4},invalidDate:"Fecha inválida"})})),function(t,e){e(h())}(0,(function(t){ +var e="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),i="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),n=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],r=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;return t.defineLocale("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(t,n){return t?/-MMM-/.test(n)?i[t.month()]:e[t.month()]:e},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",w:"una semana",ww:"%d semanas",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4},invalidDate:"Fecha inválida"})})),function(t,e){e(l())}(0,(function(t){ //! moment.js locale configuration -var e=/(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?|janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,i=[/^janv/i,/^févr/i,/^mars/i,/^avr/i,/^mai/i,/^juin/i,/^juil/i,/^août/i,/^sept/i,/^oct/i,/^nov/i,/^déc/i],n=t.defineLocale("fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsRegex:e,monthsShortRegex:e,monthsStrictRegex:/^(janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,monthsShortStrictRegex:/(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?)/i,monthsParse:i,longMonthsParse:i,shortMonthsParse:i,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",w:"une semaine",ww:"%d semaines",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|)/,ordinal:function(t,e){switch(e){case"D":return t+(1===t?"er":"");default:case"M":case"Q":case"DDD":case"d":return t+(1===t?"er":"e");case"w":case"W":return t+(1===t?"re":"e")}},week:{dow:1,doy:4}});return n})),function(t,e){e(h())}(0,(function(t){return t.defineLocale("it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato".split("_"),weekdaysShort:"dom_lun_mar_mer_gio_ven_sab".split("_"),weekdaysMin:"do_lu_ma_me_gi_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:function(){return"[Oggi a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},nextDay:function(){return"[Domani a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},nextWeek:function(){return"dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},lastDay:function(){return"[Ieri a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},lastWeek:function(){return 0===this.day()?"[La scorsa] dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT":"[Lo scorso] dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},sameElse:"L"},relativeTime:{future:"tra %s",past:"%s fa",s:"alcuni secondi",ss:"%d secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",w:"una settimana",ww:"%d settimane",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})})),function(t,e){e(h())}(0,(function(t){ +var e=/(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?|janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,i=[/^janv/i,/^févr/i,/^mars/i,/^avr/i,/^mai/i,/^juin/i,/^juil/i,/^août/i,/^sept/i,/^oct/i,/^nov/i,/^déc/i],n=t.defineLocale("fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsRegex:e,monthsShortRegex:e,monthsStrictRegex:/^(janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i,monthsShortStrictRegex:/(janv\.?|févr\.?|mars|avr\.?|mai|juin|juil\.?|août|sept\.?|oct\.?|nov\.?|déc\.?)/i,monthsParse:i,longMonthsParse:i,shortMonthsParse:i,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",w:"une semaine",ww:"%d semaines",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|)/,ordinal:function(t,e){switch(e){case"D":return t+(1===t?"er":"");default:case"M":case"Q":case"DDD":case"d":return t+(1===t?"er":"e");case"w":case"W":return t+(1===t?"re":"e")}},week:{dow:1,doy:4}});return n})),function(t,e){e(l())}(0,(function(t){return t.defineLocale("it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato".split("_"),weekdaysShort:"dom_lun_mar_mer_gio_ven_sab".split("_"),weekdaysMin:"do_lu_ma_me_gi_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:function(){return"[Oggi a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},nextDay:function(){return"[Domani a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},nextWeek:function(){return"dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},lastDay:function(){return"[Ieri a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},lastWeek:function(){return 0===this.day()?"[La scorsa] dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT":"[Lo scorso] dddd [a"+(this.hours()>1?"lle ":0===this.hours()?" ":"ll'")+"]LT"},sameElse:"L"},relativeTime:{future:"tra %s",past:"%s fa",s:"alcuni secondi",ss:"%d secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",w:"una settimana",ww:"%d settimane",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})})),function(t,e){e(l())}(0,(function(t){ //! moment.js locale configuration -var e=t.defineLocale("ja",{eras:[{since:"2019-05-01",offset:1,name:"令和",narrow:"㋿",abbr:"R"},{since:"1989-01-08",until:"2019-04-30",offset:1,name:"平成",narrow:"㍻",abbr:"H"},{since:"1926-12-25",until:"1989-01-07",offset:1,name:"昭和",narrow:"㍼",abbr:"S"},{since:"1912-07-30",until:"1926-12-24",offset:1,name:"大正",narrow:"㍽",abbr:"T"},{since:"1873-01-01",until:"1912-07-29",offset:6,name:"明治",narrow:"㍾",abbr:"M"},{since:"0001-01-01",until:"1873-12-31",offset:1,name:"西暦",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"紀元前",narrow:"BC",abbr:"BC"}],eraYearOrdinalRegex:/(元|\d+)年/,eraYearOrdinalParse:function(t,e){return"元"===e[1]?1:parseInt(e[1]||t,10)},months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日 dddd HH:mm",l:"YYYY/MM/DD",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日(ddd) HH:mm"},meridiemParse:/午前|午後/i,isPM:function(t){return"午後"===t},meridiem:function(t,e,i){return t<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:function(t){return t.week()!==this.week()?"[来週]dddd LT":"dddd LT"},lastDay:"[昨日] LT",lastWeek:function(t){return this.week()!==t.week()?"[先週]dddd LT":"dddd LT"},sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}日/,ordinal:function(t,e){switch(e){case"y":return 1===t?"元年":t+"年";case"d":case"D":case"DDD":return t+"日";default:return t}},relativeTime:{future:"%s後",past:"%s前",s:"数秒",ss:"%d秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}});return e})),function(t,e){e(h())}(0,(function(t){ +var e=t.defineLocale("ja",{eras:[{since:"2019-05-01",offset:1,name:"令和",narrow:"㋿",abbr:"R"},{since:"1989-01-08",until:"2019-04-30",offset:1,name:"平成",narrow:"㍻",abbr:"H"},{since:"1926-12-25",until:"1989-01-07",offset:1,name:"昭和",narrow:"㍼",abbr:"S"},{since:"1912-07-30",until:"1926-12-24",offset:1,name:"大正",narrow:"㍽",abbr:"T"},{since:"1873-01-01",until:"1912-07-29",offset:6,name:"明治",narrow:"㍾",abbr:"M"},{since:"0001-01-01",until:"1873-12-31",offset:1,name:"西暦",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"紀元前",narrow:"BC",abbr:"BC"}],eraYearOrdinalRegex:/(元|\d+)年/,eraYearOrdinalParse:function(t,e){return"元"===e[1]?1:parseInt(e[1]||t,10)},months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日 dddd HH:mm",l:"YYYY/MM/DD",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日(ddd) HH:mm"},meridiemParse:/午前|午後/i,isPM:function(t){return"午後"===t},meridiem:function(t,e,i){return t<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:function(t){return t.week()!==this.week()?"[来週]dddd LT":"dddd LT"},lastDay:"[昨日] LT",lastWeek:function(t){return this.week()!==t.week()?"[先週]dddd LT":"dddd LT"},sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}日/,ordinal:function(t,e){switch(e){case"y":return 1===t?"元年":t+"年";case"d":case"D":case"DDD":return t+"日";default:return t}},relativeTime:{future:"%s後",past:"%s前",s:"数秒",ss:"%d秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}});return e})),function(t,e){e(l())}(0,(function(t){ //! moment.js locale configuration -var e="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),i="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),n=[/^jan/i,/^feb/i,/^maart|mrt.?$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],r=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,o=t.defineLocale("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(t,n){return t?/-MMM-/.test(n)?i[t.month()]:e[t.month()]:e},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",w:"één week",ww:"%d weken",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(t){return t+(1===t||8===t||t>=20?"ste":"de")},week:{dow:1,doy:4}});return o})),function(t,e){e(h())}(0,(function(t){ +var e="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),i="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),n=[/^jan/i,/^feb/i,/^maart|mrt.?$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],r=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,o=t.defineLocale("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(t,n){return t?/-MMM-/.test(n)?i[t.month()]:e[t.month()]:e},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",w:"één week",ww:"%d weken",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(t){return t+(1===t||8===t||t>=20?"ste":"de")},week:{dow:1,doy:4}});return o})),function(t,e){e(l())}(0,(function(t){ //! moment.js locale configuration -var e="styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),i="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_"),n=[/^sty/i,/^lut/i,/^mar/i,/^kwi/i,/^maj/i,/^cze/i,/^lip/i,/^sie/i,/^wrz/i,/^paź/i,/^lis/i,/^gru/i];function r(t){return t%10<5&&t%10>1&&~~(t/10)%10!=1}function o(t,e,i){var n=t+" ";switch(i){case"ss":return n+(r(t)?"sekundy":"sekund");case"m":return e?"minuta":"minutę";case"mm":return n+(r(t)?"minuty":"minut");case"h":return e?"godzina":"godzinę";case"hh":return n+(r(t)?"godziny":"godzin");case"ww":return n+(r(t)?"tygodnie":"tygodni");case"MM":return n+(r(t)?"miesiące":"miesięcy");case"yy":return n+(r(t)?"lata":"lat")}}return t.defineLocale("pl",{months:function(t,n){return t?/D MMMM/.test(n)?i[t.month()]:e[t.month()]:e},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"ndz_pon_wt_śr_czw_pt_sob".split("_"),weekdaysMin:"Nd_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:function(){switch(this.day()){case 0:return"[W niedzielę o] LT";case 2:return"[We wtorek o] LT";case 3:return"[W środę o] LT";case 6:return"[W sobotę o] LT";default:return"[W] dddd [o] LT"}},lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",ss:o,m:o,mm:o,h:o,hh:o,d:"1 dzień",dd:"%d dni",w:"tydzień",ww:o,M:"miesiąc",MM:o,y:"rok",yy:o},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})),function(t,e){e(h())}(0,(function(t){function e(t,e,i){var n,r;return"m"===i?e?"минута":"минуту":t+" "+(n=+t,r={ss:e?"секунда_секунды_секунд":"секунду_секунды_секунд",mm:e?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",ww:"неделя_недели_недель",MM:"месяц_месяца_месяцев",yy:"год_года_лет"}[i].split("_"),n%10==1&&n%100!=11?r[0]:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?r[1]:r[2])}var i=[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[йя]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i],n=t.defineLocale("ru",{months:{format:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_"),standalone:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_")},monthsShort:{format:"янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.".split("_"),standalone:"янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.".split("_")},weekdays:{standalone:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),format:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_"),isFormat:/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?] ?dddd/},weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:i,longMonthsParse:i,shortMonthsParse:i,monthsRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsShortRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsStrictRegex:/^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,monthsShortStrictRegex:/^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., H:mm",LLLL:"dddd, D MMMM YYYY г., H:mm"},calendar:{sameDay:"[Сегодня, в] LT",nextDay:"[Завтра, в] LT",lastDay:"[Вчера, в] LT",nextWeek:function(t){if(t.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В следующее] dddd, [в] LT";case 1:case 2:case 4:return"[В следующий] dddd, [в] LT";case 3:case 5:case 6:return"[В следующую] dddd, [в] LT"}},lastWeek:function(t){if(t.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd, [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd, [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd, [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",ss:e,m:e,mm:e,h:"час",hh:e,d:"день",dd:e,w:"неделя",ww:e,M:"месяц",MM:e,y:"год",yy:e},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(t){return/^(дня|вечера)$/.test(t)},meridiem:function(t,e,i){return t<4?"ночи":t<12?"утра":t<17?"дня":"вечера"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(t,e){switch(e){case"M":case"d":case"DDD":return t+"-й";case"D":return t+"-го";case"w":case"W":return t+"-я";default:return t}},week:{dow:1,doy:4}});return n})),function(t,e){e(h())}(0,(function(t){function e(t,e,i){var n,r;return"m"===i?e?"хвилина":"хвилину":"h"===i?e?"година":"годину":t+" "+(n=+t,r={ss:e?"секунда_секунди_секунд":"секунду_секунди_секунд",mm:e?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:e?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"}[i].split("_"),n%10==1&&n%100!=11?r[0]:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?r[1]:r[2])}function i(t){return function(){return t+"о"+(11===this.hours()?"б":"")+"] LT"}}var n=t.defineLocale("uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:function(t,e){var i={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")};return!0===t?i.nominative.slice(1,7).concat(i.nominative.slice(0,1)):t?i[/(\[[ВвУу]\]) ?dddd/.test(e)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(e)?"genitive":"nominative"][t.day()]:i.nominative},weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:i("[Сьогодні "),nextDay:i("[Завтра "),lastDay:i("[Вчора "),nextWeek:i("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return i("[Минулої] dddd [").call(this);case 1:case 2:case 4:return i("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",ss:e,m:e,mm:e,h:"годину",hh:e,d:"день",dd:e,M:"місяць",MM:e,y:"рік",yy:e},meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(t){return/^(дня|вечора)$/.test(t)},meridiem:function(t,e,i){return t<4?"ночі":t<12?"ранку":t<17?"дня":"вечора"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го)/,ordinal:function(t,e){switch(e){case"M":case"d":case"DDD":case"w":case"W":return t+"-й";case"D":return t+"-го";default:return t}},week:{dow:1,doy:7}});return n}));var u={},c={get exports(){return u},set exports(t){u=t}},d=function(t){try{return!!t()}catch(t){return!0}},p=!d((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),f=p,m=Function.prototype,v=m.call,g=f&&m.bind.bind(v,v),y=f?g:function(t){return function(){return v.apply(t,arguments)}},b=Math.ceil,_=Math.floor,w=Math.trunc||function(t){var e=+t;return(e>0?_:b)(e)},k=function(t){var e=+t;return e!=e||0===e?0:w(e)},x=function(t){return t&&t.Math==Math&&t},D=x("object"==typeof globalThis&&globalThis)||x("object"==typeof window&&window)||x("object"==typeof self&&self)||x("object"==typeof e&&e)||function(){return this}()||Function("return this")(),S={},C={get exports(){return S},set exports(t){S=t}},T=D,M=Object.defineProperty,O=function(t,e){try{M(T,t,{value:e,configurable:!0,writable:!0})}catch(i){T[t]=e}return e},E="__core-js_shared__",P=D[E]||O(E,{}),I=P;(C.exports=function(t,e){return I[t]||(I[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.29.0",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.29.0/LICENSE",source:"https://github.com/zloirock/core-js"});var A,L,N=function(t){return null==t},R=N,F=TypeError,j=function(t){if(R(t))throw F("Can't call method on "+t);return t},Y=j,H=Object,z=function(t){return H(Y(t))},B=z,G=y({}.hasOwnProperty),W=Object.hasOwn||function(t,e){return G(B(t),e)},V=y,U=0,X=Math.random(),q=V(1..toString),$=function(t){return"Symbol("+(void 0===t?"":t)+")_"+q(++U+X,36)},Z="undefined"!=typeof navigator&&String(navigator.userAgent)||"",K=D,J=Z,Q=K.process,tt=K.Deno,et=Q&&Q.versions||tt&&tt.version,it=et&&et.v8;it&&(L=(A=it.split("."))[0]>0&&A[0]<4?1:+(A[0]+A[1])),!L&&J&&(!(A=J.match(/Edge\/(\d+)/))||A[1]>=74)&&(A=J.match(/Chrome\/(\d+)/))&&(L=+A[1]);var nt=L,rt=nt,ot=d,st=!!Object.getOwnPropertySymbols&&!ot((function(){var t=Symbol();return!String(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&rt&&rt<41})),at=st&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,lt=S,ht=W,ut=$,ct=st,dt=at,pt=D.Symbol,ft=lt("wks"),mt=dt?pt.for||pt:pt&&pt.withoutSetter||ut,vt=function(t){return ht(ft,t)||(ft[t]=ct&&ht(pt,t)?pt[t]:mt("Symbol."+t)),ft[t]},gt={};gt[vt("toStringTag")]="z";var yt="[object z]"===String(gt),bt="object"==typeof document&&document.all,_t={all:bt,IS_HTMLDDA:void 0===bt&&void 0!==bt},wt=_t.all,kt=_t.IS_HTMLDDA?function(t){return"function"==typeof t||t===wt}:function(t){return"function"==typeof t},xt=y,Dt=xt({}.toString),St=xt("".slice),Ct=function(t){return St(Dt(t),8,-1)},Tt=yt,Mt=kt,Ot=Ct,Et=vt("toStringTag"),Pt=Object,It="Arguments"==Ot(function(){return arguments}()),At=Tt?Ot:function(t){var e,i,n;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(i=function(t,e){try{return t[e]}catch(t){}}(e=Pt(t),Et))?i:It?Ot(e):"Object"==(n=Ot(e))&&Mt(e.callee)?"Arguments":n},Lt=At,Nt=String,Rt=function(t){if("Symbol"===Lt(t))throw TypeError("Cannot convert a Symbol value to a string");return Nt(t)},Ft=y,jt=k,Yt=Rt,Ht=j,zt=Ft("".charAt),Bt=Ft("".charCodeAt),Gt=Ft("".slice),Wt=function(t){return function(e,i){var n,r,o=Yt(Ht(e)),s=jt(i),a=o.length;return s<0||s>=a?t?"":void 0:(n=Bt(o,s))<55296||n>56319||s+1===a||(r=Bt(o,s+1))<56320||r>57343?t?zt(o,s):n:t?Gt(o,s,s+2):r-56320+(n-55296<<10)+65536}},Vt={codeAt:Wt(!1),charAt:Wt(!0)},Ut=kt,Xt=D.WeakMap,qt=Ut(Xt)&&/native code/.test(String(Xt)),$t=kt,Zt=_t.all,Kt=_t.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:$t(t)||t===Zt}:function(t){return"object"==typeof t?null!==t:$t(t)},Jt=!d((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),Qt={},te=Kt,ee=D.document,ie=te(ee)&&te(ee.createElement),ne=function(t){return ie?ee.createElement(t):{}},re=ne,oe=!Jt&&!d((function(){return 7!=Object.defineProperty(re("div"),"a",{get:function(){return 7}}).a})),se=Jt&&d((function(){return 42!=Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),ae=Kt,le=String,he=TypeError,ue=function(t){if(ae(t))return t;throw he(le(t)+" is not an object")},ce=p,de=Function.prototype.call,pe=ce?de.bind(de):function(){return de.apply(de,arguments)},fe={},me=fe,ve=D,ge=kt,ye=function(t){return ge(t)?t:void 0},be=function(t,e){return arguments.length<2?ye(me[t])||ye(ve[t]):me[t]&&me[t][e]||ve[t]&&ve[t][e]},_e=y({}.isPrototypeOf),we=be,ke=kt,xe=_e,De=Object,Se=at?function(t){return"symbol"==typeof t}:function(t){var e=we("Symbol");return ke(e)&&xe(e.prototype,De(t))},Ce=String,Te=function(t){try{return Ce(t)}catch(t){return"Object"}},Me=kt,Oe=Te,Ee=TypeError,Pe=function(t){if(Me(t))return t;throw Ee(Oe(t)+" is not a function")},Ie=Pe,Ae=N,Le=function(t,e){var i=t[e];return Ae(i)?void 0:Ie(i)},Ne=pe,Re=kt,Fe=Kt,je=TypeError,Ye=pe,He=Kt,ze=Se,Be=Le,Ge=function(t,e){var i,n;if("string"===e&&Re(i=t.toString)&&!Fe(n=Ne(i,t)))return n;if(Re(i=t.valueOf)&&!Fe(n=Ne(i,t)))return n;if("string"!==e&&Re(i=t.toString)&&!Fe(n=Ne(i,t)))return n;throw je("Can't convert object to primitive value")},We=TypeError,Ve=vt("toPrimitive"),Ue=function(t,e){if(!He(t)||ze(t))return t;var i,n=Be(t,Ve);if(n){if(void 0===e&&(e="default"),i=Ye(n,t,e),!He(i)||ze(i))return i;throw We("Can't convert object to primitive value")}return void 0===e&&(e="number"),Ge(t,e)},Xe=Se,qe=function(t){var e=Ue(t,"string");return Xe(e)?e:e+""},$e=Jt,Ze=oe,Ke=se,Je=ue,Qe=qe,ti=TypeError,ei=Object.defineProperty,ii=Object.getOwnPropertyDescriptor,ni="enumerable",ri="configurable",oi="writable";Qt.f=$e?Ke?function(t,e,i){if(Je(t),e=Qe(e),Je(i),"function"==typeof t&&"prototype"===e&&"value"in i&&oi in i&&!i[oi]){var n=ii(t,e);n&&n[oi]&&(t[e]=i.value,i={configurable:ri in i?i[ri]:n[ri],enumerable:ni in i?i[ni]:n[ni],writable:!1})}return ei(t,e,i)}:ei:function(t,e,i){if(Je(t),e=Qe(e),Je(i),Ze)try{return ei(t,e,i)}catch(t){}if("get"in i||"set"in i)throw ti("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var si,ai,li,hi=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},ui=Qt,ci=hi,di=Jt?function(t,e,i){return ui.f(t,e,ci(1,i))}:function(t,e,i){return t[e]=i,t},pi=$,fi=S("keys"),mi=function(t){return fi[t]||(fi[t]=pi(t))},vi={},gi=qt,yi=D,bi=Kt,_i=di,wi=W,ki=P,xi=mi,Di=vi,Si="Object already initialized",Ci=yi.TypeError,Ti=yi.WeakMap;if(gi||ki.state){var Mi=ki.state||(ki.state=new Ti);Mi.get=Mi.get,Mi.has=Mi.has,Mi.set=Mi.set,si=function(t,e){if(Mi.has(t))throw Ci(Si);return e.facade=t,Mi.set(t,e),e},ai=function(t){return Mi.get(t)||{}},li=function(t){return Mi.has(t)}}else{var Oi=xi("state");Di[Oi]=!0,si=function(t,e){if(wi(t,Oi))throw Ci(Si);return e.facade=t,_i(t,Oi,e),e},ai=function(t){return wi(t,Oi)?t[Oi]:{}},li=function(t){return wi(t,Oi)}}var Ei={set:si,get:ai,has:li,enforce:function(t){return li(t)?ai(t):si(t,{})},getterFor:function(t){return function(e){var i;if(!bi(e)||(i=ai(e)).type!==t)throw Ci("Incompatible receiver, "+t+" required");return i}}},Pi=p,Ii=Function.prototype,Ai=Ii.apply,Li=Ii.call,Ni="object"==typeof Reflect&&Reflect.apply||(Pi?Li.bind(Ai):function(){return Li.apply(Ai,arguments)}),Ri=Ct,Fi=y,ji=function(t){if("Function"===Ri(t))return Fi(t)},Yi={},Hi={},zi={}.propertyIsEnumerable,Bi=Object.getOwnPropertyDescriptor,Gi=Bi&&!zi.call({1:2},1);Hi.f=Gi?function(t){var e=Bi(this,t);return!!e&&e.enumerable}:zi;var Wi=d,Vi=Ct,Ui=Object,Xi=y("".split),qi=Wi((function(){return!Ui("z").propertyIsEnumerable(0)}))?function(t){return"String"==Vi(t)?Xi(t,""):Ui(t)}:Ui,$i=qi,Zi=j,Ki=function(t){return $i(Zi(t))},Ji=Jt,Qi=pe,tn=Hi,en=hi,nn=Ki,rn=qe,on=W,sn=oe,an=Object.getOwnPropertyDescriptor;Yi.f=Ji?an:function(t,e){if(t=nn(t),e=rn(e),sn)try{return an(t,e)}catch(t){}if(on(t,e))return en(!Qi(tn.f,t,e),t[e])};var ln=d,hn=kt,un=/#|\.prototype\./,cn=function(t,e){var i=pn[dn(t)];return i==mn||i!=fn&&(hn(e)?ln(e):!!e)},dn=cn.normalize=function(t){return String(t).replace(un,".").toLowerCase()},pn=cn.data={},fn=cn.NATIVE="N",mn=cn.POLYFILL="P",vn=cn,gn=Pe,yn=p,bn=ji(ji.bind),_n=function(t,e){return gn(t),void 0===e?t:yn?bn(t,e):function(){return t.apply(e,arguments)}},wn=D,kn=Ni,xn=ji,Dn=kt,Sn=Yi.f,Cn=vn,Tn=fe,Mn=_n,On=di,En=W,Pn=function(t){var e=function(i,n,r){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,n)}return new t(i,n,r)}return kn(t,this,arguments)};return e.prototype=t.prototype,e},In=function(t,e){var i,n,r,o,s,a,l,h,u,c=t.target,d=t.global,p=t.stat,f=t.proto,m=d?wn:p?wn[c]:(wn[c]||{}).prototype,v=d?Tn:Tn[c]||On(Tn,c,{})[c],g=v.prototype;for(o in e)n=!(i=Cn(d?o:c+(p?".":"#")+o,t.forced))&&m&&En(m,o),a=v[o],n&&(l=t.dontCallGetSet?(u=Sn(m,o))&&u.value:m[o]),s=n&&l?l:e[o],n&&typeof a==typeof s||(h=t.bind&&n?Mn(s,wn):t.wrap&&n?Pn(s):f&&Dn(s)?xn(s):s,(t.sham||s&&s.sham||a&&a.sham)&&On(h,"sham",!0),On(v,o,h),f&&(En(Tn,r=c+"Prototype")||On(Tn,r,{}),On(Tn[r],o,s),t.real&&g&&(i||!g[o])&&On(g,o,s)))},An=Jt,Ln=W,Nn=Function.prototype,Rn=An&&Object.getOwnPropertyDescriptor,Fn=Ln(Nn,"name"),jn={EXISTS:Fn,PROPER:Fn&&"something"===function(){}.name,CONFIGURABLE:Fn&&(!An||An&&Rn(Nn,"name").configurable)},Yn={},Hn=k,zn=Math.max,Bn=Math.min,Gn=function(t,e){var i=Hn(t);return i<0?zn(i+e,0):Bn(i,e)},Wn=k,Vn=Math.min,Un=function(t){return t>0?Vn(Wn(t),9007199254740991):0},Xn=function(t){return Un(t.length)},qn=Ki,$n=Gn,Zn=Xn,Kn=function(t){return function(e,i,n){var r,o=qn(e),s=Zn(o),a=$n(n,s);if(t&&i!=i){for(;s>a;)if((r=o[a++])!=r)return!0}else for(;s>a;a++)if((t||a in o)&&o[a]===i)return t||a||0;return!t&&-1}},Jn={includes:Kn(!0),indexOf:Kn(!1)},Qn=W,tr=Ki,er=Jn.indexOf,ir=vi,nr=y([].push),rr=function(t,e){var i,n=tr(t),r=0,o=[];for(i in n)!Qn(ir,i)&&Qn(n,i)&&nr(o,i);for(;e.length>r;)Qn(n,i=e[r++])&&(~er(o,i)||nr(o,i));return o},or=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],sr=rr,ar=or,lr=Object.keys||function(t){return sr(t,ar)},hr=Jt,ur=se,cr=Qt,dr=ue,pr=Ki,fr=lr;Yn.f=hr&&!ur?Object.defineProperties:function(t,e){dr(t);for(var i,n=pr(e),r=fr(e),o=r.length,s=0;o>s;)cr.f(t,i=r[s++],n[i]);return t};var mr,vr=be("document","documentElement"),gr=ue,yr=Yn,br=or,_r=vi,wr=vr,kr=ne,xr="prototype",Dr="script",Sr=mi("IE_PROTO"),Cr=function(){},Tr=function(t){return"<"+Dr+">"+t+""},Mr=function(t){t.write(Tr("")),t.close();var e=t.parentWindow.Object;return t=null,e},Or=function(){try{mr=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;Or="undefined"!=typeof document?document.domain&&mr?Mr(mr):(e=kr("iframe"),i="java"+Dr+":",e.style.display="none",wr.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(Tr("document.F=Object")),t.close(),t.F):Mr(mr);for(var n=br.length;n--;)delete Or[xr][br[n]];return Or()};_r[Sr]=!0;var Er,Pr,Ir,Ar=Object.create||function(t,e){var i;return null!==t?(Cr[xr]=gr(t),i=new Cr,Cr[xr]=null,i[Sr]=t):i=Or(),void 0===e?i:yr.f(i,e)},Lr=!d((function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype})),Nr=W,Rr=kt,Fr=z,jr=Lr,Yr=mi("IE_PROTO"),Hr=Object,zr=Hr.prototype,Br=jr?Hr.getPrototypeOf:function(t){var e=Fr(t);if(Nr(e,Yr))return e[Yr];var i=e.constructor;return Rr(i)&&e instanceof i?i.prototype:e instanceof Hr?zr:null},Gr=di,Wr=function(t,e,i,n){return n&&n.enumerable?t[e]=i:Gr(t,e,i),t},Vr=d,Ur=kt,Xr=Kt,qr=Ar,$r=Br,Zr=Wr,Kr=vt("iterator"),Jr=!1;[].keys&&("next"in(Ir=[].keys())?(Pr=$r($r(Ir)))!==Object.prototype&&(Er=Pr):Jr=!0);var Qr=!Xr(Er)||Vr((function(){var t={};return Er[Kr].call(t)!==t}));Ur((Er=Qr?{}:qr(Er))[Kr])||Zr(Er,Kr,(function(){return this}));var to={IteratorPrototype:Er,BUGGY_SAFARI_ITERATORS:Jr},eo=At,io=yt?{}.toString:function(){return"[object "+eo(this)+"]"},no=yt,ro=Qt.f,oo=di,so=W,ao=io,lo=vt("toStringTag"),ho=function(t,e,i,n){if(t){var r=i?t:t.prototype;so(r,lo)||ro(r,lo,{configurable:!0,value:e}),n&&!no&&oo(r,"toString",ao)}},uo={},co=to.IteratorPrototype,po=Ar,fo=hi,mo=ho,vo=uo,go=function(){return this},yo=y,bo=Pe,_o=kt,wo=String,ko=TypeError,xo=function(t,e,i){try{return yo(bo(Object.getOwnPropertyDescriptor(t,e)[i]))}catch(t){}},Do=ue,So=function(t){if("object"==typeof t||_o(t))return t;throw ko("Can't set "+wo(t)+" as a prototype")},Co=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,i={};try{(t=xo(Object.prototype,"__proto__","set"))(i,[]),e=i instanceof Array}catch(t){}return function(i,n){return Do(i),So(n),e?t(i,n):i.__proto__=n,i}}():void 0),To=In,Mo=pe,Oo=function(t,e,i,n){var r=e+" Iterator";return t.prototype=po(co,{next:fo(+!n,i)}),mo(t,r,!1,!0),vo[r]=go,t},Eo=Br,Po=ho,Io=Wr,Ao=uo,Lo=jn.PROPER,No=to.BUGGY_SAFARI_ITERATORS,Ro=vt("iterator"),Fo="keys",jo="values",Yo="entries",Ho=function(){return this},zo=function(t,e,i,n,r,o,s){Oo(i,e,n);var a,l,h,u=function(t){if(t===r&&m)return m;if(!No&&t in p)return p[t];switch(t){case Fo:case jo:case Yo:return function(){return new i(this,t)}}return function(){return new i(this)}},c=e+" Iterator",d=!1,p=t.prototype,f=p[Ro]||p["@@iterator"]||r&&p[r],m=!No&&f||u(r),v="Array"==e&&p.entries||f;if(v&&(a=Eo(v.call(new t)))!==Object.prototype&&a.next&&(Po(a,c,!0,!0),Ao[c]=Ho),Lo&&r==jo&&f&&f.name!==jo&&(d=!0,m=function(){return Mo(f,this)}),r)if(l={values:u(jo),keys:o?m:u(Fo),entries:u(Yo)},s)for(h in l)(No||d||!(h in p))&&Io(p,h,l[h]);else To({target:e,proto:!0,forced:No||d},l);return s&&p[Ro]!==m&&Io(p,Ro,m,{name:r}),Ao[e]=m,l},Bo=function(t,e){return{value:t,done:e}},Go=Vt.charAt,Wo=Rt,Vo=Ei,Uo=zo,Xo=Bo,qo="String Iterator",$o=Vo.set,Zo=Vo.getterFor(qo);Uo(String,"String",(function(t){$o(this,{type:qo,string:Wo(t),index:0})}),(function(){var t,e=Zo(this),i=e.string,n=e.index;return n>=i.length?Xo(void 0,!0):(t=Go(i,n),e.index+=t.length,Xo(t,!1))}));var Ko=pe,Jo=ue,Qo=Le,ts=function(t,e,i){var n,r;Jo(t);try{if(!(n=Qo(t,"return"))){if("throw"===e)throw i;return i}n=Ko(n,t)}catch(t){r=!0,n=t}if("throw"===e)throw i;if(r)throw n;return Jo(n),i},es=ue,is=ts,ns=uo,rs=vt("iterator"),os=Array.prototype,ss=function(t){return void 0!==t&&(ns.Array===t||os[rs]===t)},as=kt,ls=P,hs=y(Function.toString);as(ls.inspectSource)||(ls.inspectSource=function(t){return hs(t)});var us=ls.inspectSource,cs=y,ds=d,ps=kt,fs=At,ms=us,vs=function(){},gs=[],ys=be("Reflect","construct"),bs=/^\s*(?:class|function)\b/,_s=cs(bs.exec),ws=!bs.exec(vs),ks=function(t){if(!ps(t))return!1;try{return ys(vs,gs,t),!0}catch(t){return!1}},xs=function(t){if(!ps(t))return!1;switch(fs(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return ws||!!_s(bs,ms(t))}catch(t){return!0}};xs.sham=!0;var Ds=!ys||ds((function(){var t;return ks(ks.call)||!ks(Object)||!ks((function(){t=!0}))||t}))?xs:ks,Ss=qe,Cs=Qt,Ts=hi,Ms=function(t,e,i){var n=Ss(e);n in t?Cs.f(t,n,Ts(0,i)):t[n]=i},Os=At,Es=Le,Ps=N,Is=uo,As=vt("iterator"),Ls=function(t){if(!Ps(t))return Es(t,As)||Es(t,"@@iterator")||Is[Os(t)]},Ns=pe,Rs=Pe,Fs=ue,js=Te,Ys=Ls,Hs=TypeError,zs=function(t,e){var i=arguments.length<2?Ys(t):e;if(Rs(i))return Fs(Ns(i,t));throw Hs(js(t)+" is not iterable")},Bs=_n,Gs=pe,Ws=z,Vs=function(t,e,i,n){try{return n?e(es(i)[0],i[1]):e(i)}catch(e){is(t,"throw",e)}},Us=ss,Xs=Ds,qs=Xn,$s=Ms,Zs=zs,Ks=Ls,Js=Array,Qs=vt("iterator"),ta=!1;try{var ea=0,ia={next:function(){return{done:!!ea++}},return:function(){ta=!0}};ia[Qs]=function(){return this},Array.from(ia,(function(){throw 2}))}catch(t){}var na=function(t,e){if(!e&&!ta)return!1;var i=!1;try{var n={};n[Qs]=function(){return{next:function(){return{done:i=!0}}}},t(n)}catch(t){}return i},ra=function(t){var e=Ws(t),i=Xs(this),n=arguments.length,r=n>1?arguments[1]:void 0,o=void 0!==r;o&&(r=Bs(r,n>2?arguments[2]:void 0));var s,a,l,h,u,c,d=Ks(e),p=0;if(!d||this===Js&&Us(d))for(s=qs(e),a=i?new this(s):Js(s);s>p;p++)c=o?r(e[p],p):e[p],$s(a,p,c);else for(u=(h=Zs(e,d)).next,a=i?new this:[];!(l=Gs(u,h)).done;p++)c=o?Vs(h,r,[l.value,p],!0):l.value,$s(a,p,c);return a.length=p,a};In({target:"Array",stat:!0,forced:!na((function(t){Array.from(t)}))},{from:ra});var oa=fe.Array.from;!function(t){t.exports=oa}(c);var sa=n(u),aa={},la={get exports(){return aa},set exports(t){aa=t}},ha={},ua={get exports(){return ha},set exports(t){ha=t}},ca=Ki,da=uo,pa=Ei;Qt.f;var fa=zo,ma=Bo,va="Array Iterator",ga=pa.set,ya=pa.getterFor(va);fa(Array,"Array",(function(t,e){ga(this,{type:va,target:ca(t),index:0,kind:e})}),(function(){var t=ya(this),e=t.target,i=t.kind,n=t.index++;return!e||n>=e.length?(t.target=void 0,ma(void 0,!0)):ma("keys"==i?n:"values"==i?e[n]:[n,e[n]],!1)}),"values"),da.Arguments=da.Array;var ba=Ls,_a={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},wa=D,ka=At,xa=di,Da=uo,Sa=vt("toStringTag");for(var Ca in _a){var Ta=wa[Ca],Ma=Ta&&Ta.prototype;Ma&&ka(Ma)!==Sa&&xa(Ma,Sa,Ca),Da[Ca]=Da.Array}var Oa=ba;!function(t){t.exports=Oa}(ua),function(t){t.exports=ha}(la);var Ea=n(aa),Pa={},Ia={get exports(){return Pa},set exports(t){Pa=t}},Aa={},La=rr,Na=or.concat("length","prototype");Aa.f=Object.getOwnPropertyNames||function(t){return La(t,Na)};var Ra={},Fa=Gn,ja=Xn,Ya=Ms,Ha=Array,za=Math.max,Ba=function(t,e,i){for(var n=ja(t),r=Fa(e,n),o=Fa(void 0===i?n:i,n),s=Ha(za(o-r,0)),a=0;ry;y++)if((a||y in m)&&(p=v(d=m[y],y,f),t))if(e)_[y]=p;else if(p)switch(t){case 3:return!0;case 5:return d;case 6:return y;case 2:xl(_,d)}else switch(t){case 4:return!1;case 7:xl(_,d)}return o?-1:n||r?r:_}},Sl={forEach:Dl(0),map:Dl(1),filter:Dl(2),some:Dl(3),every:Dl(4),find:Dl(5),findIndex:Dl(6),filterReject:Dl(7)},Cl=In,Tl=D,Ml=pe,Ol=y,El=Jt,Pl=st,Il=d,Al=W,Ll=_e,Nl=ue,Rl=Ki,Fl=qe,jl=Rt,Yl=hi,Hl=Ar,zl=lr,Bl=Aa,Gl=Ra,Wl=qa,Vl=Yi,Ul=Qt,Xl=Yn,ql=Hi,$l=Wr,Zl=Za,Kl=S,Jl=vi,Ql=$,th=vt,eh=Ka,ih=nl,nh=ll,rh=ho,oh=Ei,sh=Sl.forEach,ah=mi("hidden"),lh="Symbol",hh="prototype",uh=oh.set,ch=oh.getterFor(lh),dh=Object[hh],ph=Tl.Symbol,fh=ph&&ph[hh],mh=Tl.TypeError,vh=Tl.QObject,gh=Vl.f,yh=Ul.f,bh=Gl.f,_h=ql.f,wh=Ol([].push),kh=Kl("symbols"),xh=Kl("op-symbols"),Dh=Kl("wks"),Sh=!vh||!vh[hh]||!vh[hh].findChild,Ch=El&&Il((function(){return 7!=Hl(yh({},"a",{get:function(){return yh(this,"a",{value:7}).a}})).a}))?function(t,e,i){var n=gh(dh,e);n&&delete dh[e],yh(t,e,i),n&&t!==dh&&yh(dh,e,n)}:yh,Th=function(t,e){var i=kh[t]=Hl(fh);return uh(i,{type:lh,tag:t,description:e}),El||(i.description=e),i},Mh=function(t,e,i){t===dh&&Mh(xh,e,i),Nl(t);var n=Fl(e);return Nl(i),Al(kh,n)?(i.enumerable?(Al(t,ah)&&t[ah][n]&&(t[ah][n]=!1),i=Hl(i,{enumerable:Yl(0,!1)})):(Al(t,ah)||yh(t,ah,Yl(1,{})),t[ah][n]=!0),Ch(t,n,i)):yh(t,n,i)},Oh=function(t,e){Nl(t);var i=Rl(e),n=zl(i).concat(Ah(i));return sh(n,(function(e){El&&!Ml(Eh,i,e)||Mh(t,e,i[e])})),t},Eh=function(t){var e=Fl(t),i=Ml(_h,this,e);return!(this===dh&&Al(kh,e)&&!Al(xh,e))&&(!(i||!Al(this,e)||!Al(kh,e)||Al(this,ah)&&this[ah][e])||i)},Ph=function(t,e){var i=Rl(t),n=Fl(e);if(i!==dh||!Al(kh,n)||Al(xh,n)){var r=gh(i,n);return!r||!Al(kh,n)||Al(i,ah)&&i[ah][n]||(r.enumerable=!0),r}},Ih=function(t){var e=bh(Rl(t)),i=[];return sh(e,(function(t){Al(kh,t)||Al(Jl,t)||wh(i,t)})),i},Ah=function(t){var e=t===dh,i=bh(e?xh:Rl(t)),n=[];return sh(i,(function(t){!Al(kh,t)||e&&!Al(dh,t)||wh(n,kh[t])})),n};Pl||(ph=function(){if(Ll(fh,this))throw mh("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?jl(arguments[0]):void 0,e=Ql(t),i=function(t){this===dh&&Ml(i,xh,t),Al(this,ah)&&Al(this[ah],e)&&(this[ah][e]=!1),Ch(this,e,Yl(1,t))};return El&&Sh&&Ch(dh,e,{configurable:!0,set:i}),Th(e,t)},$l(fh=ph[hh],"toString",(function(){return ch(this).tag})),$l(ph,"withoutSetter",(function(t){return Th(Ql(t),t)})),ql.f=Eh,Ul.f=Mh,Xl.f=Oh,Vl.f=Ph,Bl.f=Gl.f=Ih,Wl.f=Ah,eh.f=function(t){return Th(th(t),t)},El&&Zl(fh,"description",{configurable:!0,get:function(){return ch(this).description}})),Cl({global:!0,constructor:!0,wrap:!0,forced:!Pl,sham:!Pl},{Symbol:ph}),sh(zl(Dh),(function(t){ih(t)})),Cl({target:lh,stat:!0,forced:!Pl},{useSetter:function(){Sh=!0},useSimple:function(){Sh=!1}}),Cl({target:"Object",stat:!0,forced:!Pl,sham:!El},{create:function(t,e){return void 0===e?Hl(t):Oh(Hl(t),e)},defineProperty:Mh,defineProperties:Oh,getOwnPropertyDescriptor:Ph}),Cl({target:"Object",stat:!0,forced:!Pl},{getOwnPropertyNames:Ih}),nh(),rh(ph,lh),Jl[ah]=!0;var Lh=st&&!!Symbol.for&&!!Symbol.keyFor,Nh=In,Rh=be,Fh=W,jh=Rt,Yh=S,Hh=Lh,zh=Yh("string-to-symbol-registry"),Bh=Yh("symbol-to-string-registry");Nh({target:"Symbol",stat:!0,forced:!Hh},{for:function(t){var e=jh(t);if(Fh(zh,e))return zh[e];var i=Rh("Symbol")(e);return zh[e]=i,Bh[i]=e,i}});var Gh=In,Wh=W,Vh=Se,Uh=Te,Xh=Lh,qh=S("symbol-to-string-registry");Gh({target:"Symbol",stat:!0,forced:!Xh},{keyFor:function(t){if(!Vh(t))throw TypeError(Uh(t)+" is not a symbol");if(Wh(qh,t))return qh[t]}});var $h=y([].slice),Zh=ul,Kh=kt,Jh=Ct,Qh=Rt,tu=y([].push),eu=In,iu=be,nu=Ni,ru=pe,ou=y,su=d,au=kt,lu=Se,hu=$h,uu=function(t){if(Kh(t))return t;if(Zh(t)){for(var e=t.length,i=[],n=0;na;)void 0!==(i=r(n,e=o[a++]))&&tc(s,e,i);return s}});var ec=fe.Object.getOwnPropertyDescriptors;!function(t){t.exports=ec}(Wu);var ic=n(Gu),nc={},rc={get exports(){return nc},set exports(t){nc=t}},oc={},sc={get exports(){return oc},set exports(t){oc=t}},ac=In,lc=Jt,hc=Yn.f;ac({target:"Object",stat:!0,forced:Object.defineProperties!==hc,sham:!lc},{defineProperties:hc});var uc=fe.Object,cc=sc.exports=function(t,e){return uc.defineProperties(t,e)};uc.defineProperties.sham&&(cc.sham=!0);var dc=oc;!function(t){t.exports=dc}(rc);var pc=n(nc),fc={},mc={get exports(){return fc},set exports(t){fc=t}},vc={},gc={get exports(){return vc},set exports(t){vc=t}},yc=In,bc=Jt,_c=Qt.f;yc({target:"Object",stat:!0,forced:Object.defineProperty!==_c,sham:!bc},{defineProperty:_c});var wc=fe.Object,kc=gc.exports=function(t,e,i){return wc.defineProperty(t,e,i)};wc.defineProperty.sham&&(kc.sham=!0);var xc=vc;!function(t){t.exports=xc}(mc);var Dc=n(fc);function Sc(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var Cc={},Tc={get exports(){return Cc},set exports(t){Cc=t}},Mc={},Oc=xc;!function(t){t.exports=Oc}({get exports(){return Mc},set exports(t){Mc=t}}),function(t){t.exports=Mc}(Tc);var Ec=n(Cc),Pc={},Ic={get exports(){return Pc},set exports(t){Pc=t}},Ac={},Lc={get exports(){return Ac},set exports(t){Ac=t}},Nc=TypeError,Rc=function(t){if(t>9007199254740991)throw Nc("Maximum allowed index exceeded");return t},Fc=d,jc=nt,Yc=vt("species"),Hc=function(t){return jc>=51||!Fc((function(){var e=[];return(e.constructor={})[Yc]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},zc=In,Bc=d,Gc=ul,Wc=Kt,Vc=z,Uc=Xn,Xc=Rc,qc=Ms,$c=gl,Zc=Hc,Kc=nt,Jc=vt("isConcatSpreadable"),Qc=Kc>=51||!Bc((function(){var t=[];return t[Jc]=!1,t.concat()[0]!==t})),td=function(t){if(!Wc(t))return!1;var e=t[Jc];return void 0!==e?!!e:Gc(t)};zc({target:"Array",proto:!0,arity:1,forced:!Qc||!Zc("concat")},{concat:function(t){var e,i,n,r,o,s=Vc(this),a=$c(s,0),l=0;for(e=-1,n=arguments.length;et.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?arguments[1]:void 0)}});var of=yp("Array").map,sf=_e,af=of,lf=Array.prototype,hf=function(t){var e=t.map;return t===lf||sf(lf,t)&&e===lf.map?af:e},uf=hf;!function(t){t.exports=uf}(nf);var cf=n(ef),df={},pf={get exports(){return df},set exports(t){df=t}},ff=z,mf=lr;In({target:"Object",stat:!0,forced:d((function(){mf(1)}))},{keys:function(t){return mf(ff(t))}});var vf=fe.Object.keys;!function(t){t.exports=vf}(pf);var gf=n(df),yf={},bf={get exports(){return yf},set exports(t){yf=t}},_f=In,wf=Date,kf=y(wf.prototype.getTime);_f({target:"Date",stat:!0},{now:function(){return kf(new wf)}});var xf=fe.Date.now;!function(t){t.exports=xf}(bf);var Df=n(yf),Sf={},Cf={get exports(){return Sf},set exports(t){Sf=t}},Tf=y,Mf=Pe,Of=Kt,Ef=W,Pf=$h,If=p,Af=Function,Lf=Tf([].concat),Nf=Tf([].join),Rf={},Ff=function(t,e,i){if(!Ef(Rf,e)){for(var n=[],r=0;r1?arguments[1]:void 0)};In({target:"Array",proto:!0,forced:[].forEach!=Jf},{forEach:Jf});var Qf=yp("Array").forEach,tm=At,em=W,im=_e,nm=Qf,rm=Array.prototype,om={DOMTokenList:!0,NodeList:!0},sm=function(t){var e=t.forEach;return t===rm||im(rm,t)&&e===rm.forEach||em(om,tm(t))?nm:e};!function(t){t.exports=sm}(qf);var am=n(Xf),lm={},hm={get exports(){return lm},set exports(t){lm=t}},um=In,cm=ul,dm=y([].reverse),pm=[1,2];um({target:"Array",proto:!0,forced:String(pm)===String(pm.reverse())},{reverse:function(){return cm(this)&&(this.length=this.length),dm(this)}});var fm=yp("Array").reverse,mm=_e,vm=fm,gm=Array.prototype,ym=function(t){var e=t.reverse;return t===gm||mm(gm,t)&&e===gm.reverse?vm:e},bm=ym;!function(t){t.exports=bm}(hm);var _m=n(lm),wm={},km={get exports(){return wm},set exports(t){wm=t}},xm=Jt,Dm=ul,Sm=TypeError,Cm=Object.getOwnPropertyDescriptor,Tm=xm&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(t){return t instanceof TypeError}}(),Mm=Te,Om=TypeError,Em=function(t,e){if(!delete t[e])throw Om("Cannot delete property "+Mm(e)+" of "+Mm(t))},Pm=In,Im=z,Am=Gn,Lm=k,Nm=Xn,Rm=Tm?function(t,e){if(Dm(t)&&!Cm(t,"length").writable)throw Sm("Cannot set read only .length");return t.length=e}:function(t,e){return t.length=e},Fm=Rc,jm=gl,Ym=Ms,Hm=Em,zm=Hc("splice"),Bm=Math.max,Gm=Math.min;Pm({target:"Array",proto:!0,forced:!zm},{splice:function(t,e){var i,n,r,o,s,a,l=Im(this),h=Nm(l),u=Am(t,h),c=arguments.length;for(0===c?i=n=0:1===c?(i=0,n=h-u):(i=c-2,n=Gm(Bm(Lm(e),0),h-u)),Fm(h+i-n),r=jm(l,n),o=0;oh-n+i;o--)Hm(l,o-1)}else if(i>n)for(o=h-n;o>u;o--)a=o+i-1,(s=o+n-1)in l?l[a]=l[s]:Hm(l,a);for(o=0;or;)for(var a,l=av(arguments[r++]),h=o?uv(nv(l),o(l)):nv(l),u=h.length,c=0;u>c;)a=h[c++],Qm&&!ev(s,l,a)||(i[a]=l[a]);return i}:lv,dv=cv;In({target:"Object",stat:!0,arity:2,forced:Object.assign!==dv},{assign:dv});var pv=fe.Object.assign;!function(t){t.exports=pv}(Jm);var fv=n(Km),mv={},vv={get exports(){return mv},set exports(t){mv=t}},gv=Jn.includes;In({target:"Array",proto:!0,forced:d((function(){return!Array(1).includes()}))},{includes:function(t){return gv(this,t,arguments.length>1?arguments[1]:void 0)}});var yv=yp("Array").includes,bv=Kt,_v=Ct,wv=vt("match"),kv=function(t){var e;return bv(t)&&(void 0!==(e=t[wv])?!!e:"RegExp"==_v(t))},xv=TypeError,Dv=vt("match"),Sv=In,Cv=function(t){if(kv(t))throw xv("The method doesn't accept regular expressions");return t},Tv=j,Mv=Rt,Ov=function(t){var e=/./;try{"/./"[t](e)}catch(i){try{return e[Dv]=!1,"/./"[t](e)}catch(t){}}return!1},Ev=y("".indexOf);Sv({target:"String",proto:!0,forced:!Ov("includes")},{includes:function(t){return!!~Ev(Mv(Tv(this)),Mv(Cv(t)),arguments.length>1?arguments[1]:void 0)}});var Pv=yp("String").includes,Iv=_e,Av=yv,Lv=Pv,Nv=Array.prototype,Rv=String.prototype,Fv=function(t){var e=t.includes;return t===Nv||Iv(Nv,t)&&e===Nv.includes?Av:"string"==typeof t||t===Rv||Iv(Rv,t)&&e===Rv.includes?Lv:e},jv=Fv;!function(t){t.exports=jv}(vv);var Yv=n(mv),Hv={},zv={get exports(){return Hv},set exports(t){Hv=t}},Bv=z,Gv=Br,Wv=Lr;In({target:"Object",stat:!0,forced:d((function(){Gv(1)})),sham:!Wv},{getPrototypeOf:function(t){return Gv(Bv(t))}});var Vv=fe.Object.getPrototypeOf;!function(t){t.exports=Vv}(zv);var Uv=n(Hv),Xv={},qv={get exports(){return Xv},set exports(t){Xv=t}},$v=Sl.filter;In({target:"Array",proto:!0,forced:!Hc("filter")},{filter:function(t){return $v(this,t,arguments.length>1?arguments[1]:void 0)}});var Zv=yp("Array").filter,Kv=_e,Jv=Zv,Qv=Array.prototype,tg=function(t){var e=t.filter;return t===Qv||Kv(Qv,t)&&e===Qv.filter?Jv:e},eg=tg;!function(t){t.exports=eg}(qv);var ig=n(Xv),ng={},rg={get exports(){return ng},set exports(t){ng=t}},og=Jt,sg=y,ag=lr,lg=Ki,hg=sg(Hi.f),ug=sg([].push),cg=function(t){return function(e){for(var i,n=lg(e),r=ag(n),o=r.length,s=0,a=[];o>s;)i=r[s++],og&&!hg(n,i)||ug(a,t?[i,n[i]]:n[i]);return a}},dg={entries:cg(!0),values:cg(!1)}.values;In({target:"Object",stat:!0},{values:function(t){return dg(t)}});var pg=fe.Object.values;!function(t){t.exports=pg}(rg);var fg=n(ng),mg={},vg={get exports(){return mg},set exports(t){mg=t}},gg="\t\n\v\f\r                 \u2028\u2029\ufeff",yg=j,bg=Rt,_g=gg,wg=y("".replace),kg=RegExp("^["+_g+"]+"),xg=RegExp("(^|[^"+_g+"])["+_g+"]+$"),Dg=function(t){return function(e){var i=bg(yg(e));return 1&t&&(i=wg(i,kg,"")),2&t&&(i=wg(i,xg,"$1")),i}},Sg={start:Dg(1),end:Dg(2),trim:Dg(3)},Cg=D,Tg=d,Mg=y,Og=Rt,Eg=Sg.trim,Pg=gg,Ig=Cg.parseInt,Ag=Cg.Symbol,Lg=Ag&&Ag.iterator,Ng=/^[+-]?0x/i,Rg=Mg(Ng.exec),Fg=8!==Ig(Pg+"08")||22!==Ig(Pg+"0x16")||Lg&&!Tg((function(){Ig(Object(Lg))}))?function(t,e){var i=Eg(Og(t));return Ig(i,e>>>0||(Rg(Ng,i)?16:10))}:Ig;In({global:!0,forced:parseInt!=Fg},{parseInt:Fg});var jg=fe.parseInt;!function(t){t.exports=jg}(vg);var Yg=n(mg),Hg={},zg={get exports(){return Hg},set exports(t){Hg=t}},Bg=In,Gg=Jn.indexOf,Wg=Zf,Vg=ji([].indexOf),Ug=!!Vg&&1/Vg([1],1,-0)<0;Bg({target:"Array",proto:!0,forced:Ug||!Wg("indexOf")},{indexOf:function(t){var e=arguments.length>1?arguments[1]:void 0;return Ug?Vg(this,t,e)||0:Gg(this,t,e)}});var Xg=yp("Array").indexOf,qg=_e,$g=Xg,Zg=Array.prototype,Kg=function(t){var e=t.indexOf;return t===Zg||qg(Zg,t)&&e===Zg.indexOf?$g:e},Jg=Kg;!function(t){t.exports=Jg}(zg);var Qg=n(Hg),ty={},ey={get exports(){return ty},set exports(t){ty=t}},iy=jn.PROPER,ny=d,ry=gg,oy=Sg.trim;In({target:"String",proto:!0,forced:function(t){return ny((function(){return!!ry[t]()||"​…᠎"!=="​…᠎"[t]()||iy&&ry[t].name!==t}))}("trim")},{trim:function(){return oy(this)}});var sy=yp("String").trim,ay=_e,ly=sy,hy=String.prototype,uy=function(t){var e=t.trim;return"string"==typeof t||t===hy||ay(hy,t)&&e===hy.trim?ly:e},cy=uy;!function(t){t.exports=cy}(ey);var dy=n(ty),py={},fy={get exports(){return py},set exports(t){py=t}};In({target:"Object",stat:!0,sham:!Jt},{create:Ar});var my=fe.Object,vy=function(t,e){return my.create(t,e)};!function(t){t.exports=vy}(fy);var gy=n(py),yy={},by={get exports(){return yy},set exports(t){yy=t}},_y=fe,wy=Ni;_y.JSON||(_y.JSON={stringify:JSON.stringify});var ky=function(t,e,i){return wy(_y.JSON.stringify,null,arguments)},xy=ky;!function(t){t.exports=xy}(by);var Dy=n(yy),Sy={},Cy={get exports(){return Sy},set exports(t){Sy=t}},Ty="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,My=TypeError,Oy=function(t,e){if(ti,s=Iy(n)?n:Fy(n),a=o?Ny(arguments,i):[],l=o?function(){Py(s,this,a)}:s;return e?t(l,r):t(l)}:t},Hy=In,zy=D,By=Yy(zy.setInterval,!0);Hy({global:!0,bind:!0,forced:zy.setInterval!==By},{setInterval:By});var Gy=In,Wy=D,Vy=Yy(Wy.setTimeout,!0);Gy({global:!0,bind:!0,forced:Wy.setTimeout!==Vy},{setTimeout:Vy});var Uy=fe.setTimeout;!function(t){t.exports=Uy}(Cy);var Xy=n(Sy),qy={},$y={get exports(){return qy},set exports(t){qy=t}},Zy=z,Ky=Gn,Jy=Xn,Qy=function(t){for(var e=Zy(this),i=Jy(e),n=arguments.length,r=Ky(n>1?arguments[1]:void 0,i),o=n>2?arguments[2]:void 0,s=void 0===o?i:Ky(o,i);s>r;)e[r++]=t;return e};In({target:"Array",proto:!0},{fill:Qy});var tb=yp("Array").fill,eb=_e,ib=tb,nb=Array.prototype,rb=function(t){var e=t.fill;return t===nb||eb(nb,t)&&e===nb.fill?ib:e},ob=rb;!function(t){t.exports=ob}($y);var sb=n(qy),ab={};!function(t){function e(t){if(t)return function(t){for(var i in e.prototype)t[i]=e.prototype[i];return t}(t)}t.exports=e,e.prototype.on=e.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},e.prototype.once=function(t,e){function i(){this.off(t,i),e.apply(this,arguments)}return i.fn=e,this.on(t,i),this},e.prototype.off=e.prototype.removeListener=e.prototype.removeAllListeners=e.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var i,n=this._callbacks["$"+t];if(!n)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var r=0;r1&&~~(t/10)%10!=1}function o(t,e,i){var n=t+" ";switch(i){case"ss":return n+(r(t)?"sekundy":"sekund");case"m":return e?"minuta":"minutę";case"mm":return n+(r(t)?"minuty":"minut");case"h":return e?"godzina":"godzinę";case"hh":return n+(r(t)?"godziny":"godzin");case"ww":return n+(r(t)?"tygodnie":"tygodni");case"MM":return n+(r(t)?"miesiące":"miesięcy");case"yy":return n+(r(t)?"lata":"lat")}}return t.defineLocale("pl",{months:function(t,n){return t?/D MMMM/.test(n)?i[t.month()]:e[t.month()]:e},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"ndz_pon_wt_śr_czw_pt_sob".split("_"),weekdaysMin:"Nd_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:function(){switch(this.day()){case 0:return"[W niedzielę o] LT";case 2:return"[We wtorek o] LT";case 3:return"[W środę o] LT";case 6:return"[W sobotę o] LT";default:return"[W] dddd [o] LT"}},lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",ss:o,m:o,mm:o,h:o,hh:o,d:"1 dzień",dd:"%d dni",w:"tydzień",ww:o,M:"miesiąc",MM:o,y:"rok",yy:o},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})),function(t,e){e(l())}(0,(function(t){function e(t,e,i){var n,r;return"m"===i?e?"минута":"минуту":t+" "+(n=+t,r={ss:e?"секунда_секунды_секунд":"секунду_секунды_секунд",mm:e?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",ww:"неделя_недели_недель",MM:"месяц_месяца_месяцев",yy:"год_года_лет"}[i].split("_"),n%10==1&&n%100!=11?r[0]:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?r[1]:r[2])}var i=[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[йя]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i],n=t.defineLocale("ru",{months:{format:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_"),standalone:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_")},monthsShort:{format:"янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.".split("_"),standalone:"янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.".split("_")},weekdays:{standalone:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),format:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_"),isFormat:/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?] ?dddd/},weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:i,longMonthsParse:i,shortMonthsParse:i,monthsRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsShortRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsStrictRegex:/^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,monthsShortStrictRegex:/^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., H:mm",LLLL:"dddd, D MMMM YYYY г., H:mm"},calendar:{sameDay:"[Сегодня, в] LT",nextDay:"[Завтра, в] LT",lastDay:"[Вчера, в] LT",nextWeek:function(t){if(t.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В следующее] dddd, [в] LT";case 1:case 2:case 4:return"[В следующий] dddd, [в] LT";case 3:case 5:case 6:return"[В следующую] dddd, [в] LT"}},lastWeek:function(t){if(t.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd, [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd, [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd, [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",ss:e,m:e,mm:e,h:"час",hh:e,d:"день",dd:e,w:"неделя",ww:e,M:"месяц",MM:e,y:"год",yy:e},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(t){return/^(дня|вечера)$/.test(t)},meridiem:function(t,e,i){return t<4?"ночи":t<12?"утра":t<17?"дня":"вечера"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(t,e){switch(e){case"M":case"d":case"DDD":return t+"-й";case"D":return t+"-го";case"w":case"W":return t+"-я";default:return t}},week:{dow:1,doy:4}});return n})),function(t,e){e(l())}(0,(function(t){function e(t,e,i){var n,r;return"m"===i?e?"хвилина":"хвилину":"h"===i?e?"година":"годину":t+" "+(n=+t,r={ss:e?"секунда_секунди_секунд":"секунду_секунди_секунд",mm:e?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:e?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"}[i].split("_"),n%10==1&&n%100!=11?r[0]:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?r[1]:r[2])}function i(t){return function(){return t+"о"+(11===this.hours()?"б":"")+"] LT"}}var n=t.defineLocale("uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:function(t,e){var i={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")};return!0===t?i.nominative.slice(1,7).concat(i.nominative.slice(0,1)):t?i[/(\[[ВвУу]\]) ?dddd/.test(e)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(e)?"genitive":"nominative"][t.day()]:i.nominative},weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:i("[Сьогодні "),nextDay:i("[Завтра "),lastDay:i("[Вчора "),nextWeek:i("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return i("[Минулої] dddd [").call(this);case 1:case 2:case 4:return i("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",ss:e,m:e,mm:e,h:"годину",hh:e,d:"день",dd:e,M:"місяць",MM:e,y:"рік",yy:e},meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(t){return/^(дня|вечора)$/.test(t)},meridiem:function(t,e,i){return t<4?"ночі":t<12?"ранку":t<17?"дня":"вечора"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го)/,ordinal:function(t,e){switch(e){case"M":case"d":case"DDD":case"w":case"W":return t+"-й";case"D":return t+"-го";default:return t}},week:{dow:1,doy:7}});return n}));var h=function(t){try{return!!t()}catch(t){return!0}},u=!h((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),d=u,c=Function.prototype,p=c.call,f=d&&c.bind.bind(p,p),m=d?f:function(t){return function(){return p.apply(t,arguments)}},v=Math.ceil,g=Math.floor,y=Math.trunc||function(t){var e=+t;return(e>0?g:v)(e)},b=function(t){var e=+t;return e!=e||0===e?0:y(e)},_=function(t){return t&&t.Math===Math&&t},w=_("object"==typeof globalThis&&globalThis)||_("object"==typeof window&&window)||_("object"==typeof self&&self)||_("object"==typeof e&&e)||function(){return this}()||e||Function("return this")(),k={exports:{}},x=w,D=Object.defineProperty,S=function(t,e){try{D(x,t,{value:e,configurable:!0,writable:!0})}catch(i){x[t]=e}return e},C="__core-js_shared__",T=w[C]||S(C,{}),M=T;(k.exports=function(t,e){return M[t]||(M[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.33.0",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.0/LICENSE",source:"https://github.com/zloirock/core-js"});var O,E,P=k.exports,A=function(t){return null==t},I=A,L=TypeError,N=function(t){if(I(t))throw new L("Can't call method on "+t);return t},R=N,F=Object,j=function(t){return F(R(t))},Y=j,H=m({}.hasOwnProperty),z=Object.hasOwn||function(t,e){return H(Y(t),e)},B=m,G=0,W=Math.random(),V=B(1..toString),U=function(t){return"Symbol("+(void 0===t?"":t)+")_"+V(++G+W,36)},X="undefined"!=typeof navigator&&String(navigator.userAgent)||"",q=w,$=X,Z=q.process,K=q.Deno,J=Z&&Z.versions||K&&K.version,Q=J&&J.v8;Q&&(E=(O=Q.split("."))[0]>0&&O[0]<4?1:+(O[0]+O[1])),!E&&$&&(!(O=$.match(/Edge\/(\d+)/))||O[1]>=74)&&(O=$.match(/Chrome\/(\d+)/))&&(E=+O[1]);var tt=E,et=tt,it=h,nt=w.String,rt=!!Object.getOwnPropertySymbols&&!it((function(){var t=Symbol("symbol detection");return!nt(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&et&&et<41})),ot=rt&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,st=P,at=z,lt=U,ht=rt,ut=ot,dt=w.Symbol,ct=st("wks"),pt=ut?dt.for||dt:dt&&dt.withoutSetter||lt,ft=function(t){return at(ct,t)||(ct[t]=ht&&at(dt,t)?dt[t]:pt("Symbol."+t)),ct[t]},mt={};mt[ft("toStringTag")]="z";var vt="[object z]"===String(mt),gt="object"==typeof document&&document.all,yt={all:gt,IS_HTMLDDA:void 0===gt&&void 0!==gt},bt=yt.all,_t=yt.IS_HTMLDDA?function(t){return"function"==typeof t||t===bt}:function(t){return"function"==typeof t},wt=m,kt=wt({}.toString),xt=wt("".slice),Dt=function(t){return xt(kt(t),8,-1)},St=vt,Ct=_t,Tt=Dt,Mt=ft("toStringTag"),Ot=Object,Et="Arguments"===Tt(function(){return arguments}()),Pt=St?Tt:function(t){var e,i,n;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(i=function(t,e){try{return t[e]}catch(t){}}(e=Ot(t),Mt))?i:Et?Tt(e):"Object"===(n=Tt(e))&&Ct(e.callee)?"Arguments":n},At=Pt,It=String,Lt=function(t){if("Symbol"===At(t))throw new TypeError("Cannot convert a Symbol value to a string");return It(t)},Nt=m,Rt=b,Ft=Lt,jt=N,Yt=Nt("".charAt),Ht=Nt("".charCodeAt),zt=Nt("".slice),Bt=function(t){return function(e,i){var n,r,o=Ft(jt(e)),s=Rt(i),a=o.length;return s<0||s>=a?t?"":void 0:(n=Ht(o,s))<55296||n>56319||s+1===a||(r=Ht(o,s+1))<56320||r>57343?t?Yt(o,s):n:t?zt(o,s,s+2):r-56320+(n-55296<<10)+65536}},Gt={codeAt:Bt(!1),charAt:Bt(!0)},Wt=_t,Vt=w.WeakMap,Ut=Wt(Vt)&&/native code/.test(String(Vt)),Xt=_t,qt=yt.all,$t=yt.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:Xt(t)||t===qt}:function(t){return"object"==typeof t?null!==t:Xt(t)},Zt=!h((function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})),Kt={},Jt=$t,Qt=w.document,te=Jt(Qt)&&Jt(Qt.createElement),ee=function(t){return te?Qt.createElement(t):{}},ie=ee,ne=!Zt&&!h((function(){return 7!==Object.defineProperty(ie("div"),"a",{get:function(){return 7}}).a})),re=Zt&&h((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),oe=$t,se=String,ae=TypeError,le=function(t){if(oe(t))return t;throw new ae(se(t)+" is not an object")},he=u,ue=Function.prototype.call,de=he?ue.bind(ue):function(){return ue.apply(ue,arguments)},ce={},pe=ce,fe=w,me=_t,ve=function(t){return me(t)?t:void 0},ge=function(t,e){return arguments.length<2?ve(pe[t])||ve(fe[t]):pe[t]&&pe[t][e]||fe[t]&&fe[t][e]},ye=m({}.isPrototypeOf),be=ge,_e=_t,we=ye,ke=Object,xe=ot?function(t){return"symbol"==typeof t}:function(t){var e=be("Symbol");return _e(e)&&we(e.prototype,ke(t))},De=String,Se=function(t){try{return De(t)}catch(t){return"Object"}},Ce=_t,Te=Se,Me=TypeError,Oe=function(t){if(Ce(t))return t;throw new Me(Te(t)+" is not a function")},Ee=Oe,Pe=A,Ae=function(t,e){var i=t[e];return Pe(i)?void 0:Ee(i)},Ie=de,Le=_t,Ne=$t,Re=TypeError,Fe=de,je=$t,Ye=xe,He=Ae,ze=function(t,e){var i,n;if("string"===e&&Le(i=t.toString)&&!Ne(n=Ie(i,t)))return n;if(Le(i=t.valueOf)&&!Ne(n=Ie(i,t)))return n;if("string"!==e&&Le(i=t.toString)&&!Ne(n=Ie(i,t)))return n;throw new Re("Can't convert object to primitive value")},Be=TypeError,Ge=ft("toPrimitive"),We=function(t,e){if(!je(t)||Ye(t))return t;var i,n=He(t,Ge);if(n){if(void 0===e&&(e="default"),i=Fe(n,t,e),!je(i)||Ye(i))return i;throw new Be("Can't convert object to primitive value")}return void 0===e&&(e="number"),ze(t,e)},Ve=xe,Ue=function(t){var e=We(t,"string");return Ve(e)?e:e+""},Xe=Zt,qe=ne,$e=re,Ze=le,Ke=Ue,Je=TypeError,Qe=Object.defineProperty,ti=Object.getOwnPropertyDescriptor,ei="enumerable",ii="configurable",ni="writable";Kt.f=Xe?$e?function(t,e,i){if(Ze(t),e=Ke(e),Ze(i),"function"==typeof t&&"prototype"===e&&"value"in i&&ni in i&&!i[ni]){var n=ti(t,e);n&&n[ni]&&(t[e]=i.value,i={configurable:ii in i?i[ii]:n[ii],enumerable:ei in i?i[ei]:n[ei],writable:!1})}return Qe(t,e,i)}:Qe:function(t,e,i){if(Ze(t),e=Ke(e),Ze(i),qe)try{return Qe(t,e,i)}catch(t){}if("get"in i||"set"in i)throw new Je("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var ri,oi,si,ai=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},li=Kt,hi=ai,ui=Zt?function(t,e,i){return li.f(t,e,hi(1,i))}:function(t,e,i){return t[e]=i,t},di=U,ci=P("keys"),pi=function(t){return ci[t]||(ci[t]=di(t))},fi={},mi=Ut,vi=w,gi=$t,yi=ui,bi=z,_i=T,wi=pi,ki=fi,xi="Object already initialized",Di=vi.TypeError,Si=vi.WeakMap;if(mi||_i.state){var Ci=_i.state||(_i.state=new Si);Ci.get=Ci.get,Ci.has=Ci.has,Ci.set=Ci.set,ri=function(t,e){if(Ci.has(t))throw new Di(xi);return e.facade=t,Ci.set(t,e),e},oi=function(t){return Ci.get(t)||{}},si=function(t){return Ci.has(t)}}else{var Ti=wi("state");ki[Ti]=!0,ri=function(t,e){if(bi(t,Ti))throw new Di(xi);return e.facade=t,yi(t,Ti,e),e},oi=function(t){return bi(t,Ti)?t[Ti]:{}},si=function(t){return bi(t,Ti)}}var Mi={set:ri,get:oi,has:si,enforce:function(t){return si(t)?oi(t):ri(t,{})},getterFor:function(t){return function(e){var i;if(!gi(e)||(i=oi(e)).type!==t)throw new Di("Incompatible receiver, "+t+" required");return i}}},Oi=u,Ei=Function.prototype,Pi=Ei.apply,Ai=Ei.call,Ii="object"==typeof Reflect&&Reflect.apply||(Oi?Ai.bind(Pi):function(){return Ai.apply(Pi,arguments)}),Li=Dt,Ni=m,Ri=function(t){if("Function"===Li(t))return Ni(t)},Fi={},ji={},Yi={}.propertyIsEnumerable,Hi=Object.getOwnPropertyDescriptor,zi=Hi&&!Yi.call({1:2},1);ji.f=zi?function(t){var e=Hi(this,t);return!!e&&e.enumerable}:Yi;var Bi=h,Gi=Dt,Wi=Object,Vi=m("".split),Ui=Bi((function(){return!Wi("z").propertyIsEnumerable(0)}))?function(t){return"String"===Gi(t)?Vi(t,""):Wi(t)}:Wi,Xi=Ui,qi=N,$i=function(t){return Xi(qi(t))},Zi=Zt,Ki=de,Ji=ji,Qi=ai,tn=$i,en=Ue,nn=z,rn=ne,on=Object.getOwnPropertyDescriptor;Fi.f=Zi?on:function(t,e){if(t=tn(t),e=en(e),rn)try{return on(t,e)}catch(t){}if(nn(t,e))return Qi(!Ki(Ji.f,t,e),t[e])};var sn=h,an=_t,ln=/#|\.prototype\./,hn=function(t,e){var i=dn[un(t)];return i===pn||i!==cn&&(an(e)?sn(e):!!e)},un=hn.normalize=function(t){return String(t).replace(ln,".").toLowerCase()},dn=hn.data={},cn=hn.NATIVE="N",pn=hn.POLYFILL="P",fn=hn,mn=Oe,vn=u,gn=Ri(Ri.bind),yn=function(t,e){return mn(t),void 0===e?t:vn?gn(t,e):function(){return t.apply(e,arguments)}},bn=w,_n=Ii,wn=Ri,kn=_t,xn=Fi.f,Dn=fn,Sn=ce,Cn=yn,Tn=ui,Mn=z,On=function(t){var e=function(i,n,r){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,n)}return new t(i,n,r)}return _n(t,this,arguments)};return e.prototype=t.prototype,e},En=function(t,e){var i,n,r,o,s,a,l,h,u,d=t.target,c=t.global,p=t.stat,f=t.proto,m=c?bn:p?bn[d]:(bn[d]||{}).prototype,v=c?Sn:Sn[d]||Tn(Sn,d,{})[d],g=v.prototype;for(o in e)n=!(i=Dn(c?o:d+(p?".":"#")+o,t.forced))&&m&&Mn(m,o),a=v[o],n&&(l=t.dontCallGetSet?(u=xn(m,o))&&u.value:m[o]),s=n&&l?l:e[o],n&&typeof a==typeof s||(h=t.bind&&n?Cn(s,bn):t.wrap&&n?On(s):f&&kn(s)?wn(s):s,(t.sham||s&&s.sham||a&&a.sham)&&Tn(h,"sham",!0),Tn(v,o,h),f&&(Mn(Sn,r=d+"Prototype")||Tn(Sn,r,{}),Tn(Sn[r],o,s),t.real&&g&&(i||!g[o])&&Tn(g,o,s)))},Pn=Zt,An=z,In=Function.prototype,Ln=Pn&&Object.getOwnPropertyDescriptor,Nn=An(In,"name"),Rn={EXISTS:Nn,PROPER:Nn&&"something"===function(){}.name,CONFIGURABLE:Nn&&(!Pn||Pn&&Ln(In,"name").configurable)},Fn={},jn=b,Yn=Math.max,Hn=Math.min,zn=function(t,e){var i=jn(t);return i<0?Yn(i+e,0):Hn(i,e)},Bn=b,Gn=Math.min,Wn=function(t){return t>0?Gn(Bn(t),9007199254740991):0},Vn=function(t){return Wn(t.length)},Un=$i,Xn=zn,qn=Vn,$n=function(t){return function(e,i,n){var r,o=Un(e),s=qn(o),a=Xn(n,s);if(t&&i!=i){for(;s>a;)if((r=o[a++])!=r)return!0}else for(;s>a;a++)if((t||a in o)&&o[a]===i)return t||a||0;return!t&&-1}},Zn={includes:$n(!0),indexOf:$n(!1)},Kn=z,Jn=$i,Qn=Zn.indexOf,tr=fi,er=m([].push),ir=function(t,e){var i,n=Jn(t),r=0,o=[];for(i in n)!Kn(tr,i)&&Kn(n,i)&&er(o,i);for(;e.length>r;)Kn(n,i=e[r++])&&(~Qn(o,i)||er(o,i));return o},nr=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],rr=ir,or=nr,sr=Object.keys||function(t){return rr(t,or)},ar=Zt,lr=re,hr=Kt,ur=le,dr=$i,cr=sr;Fn.f=ar&&!lr?Object.defineProperties:function(t,e){ur(t);for(var i,n=dr(e),r=cr(e),o=r.length,s=0;o>s;)hr.f(t,i=r[s++],n[i]);return t};var pr,fr=ge("document","documentElement"),mr=le,vr=Fn,gr=nr,yr=fi,br=fr,_r=ee,wr="prototype",kr="script",xr=pi("IE_PROTO"),Dr=function(){},Sr=function(t){return"<"+kr+">"+t+""},Cr=function(t){t.write(Sr("")),t.close();var e=t.parentWindow.Object;return t=null,e},Tr=function(){try{pr=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;Tr="undefined"!=typeof document?document.domain&&pr?Cr(pr):(e=_r("iframe"),i="java"+kr+":",e.style.display="none",br.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(Sr("document.F=Object")),t.close(),t.F):Cr(pr);for(var n=gr.length;n--;)delete Tr[wr][gr[n]];return Tr()};yr[xr]=!0;var Mr,Or,Er,Pr=Object.create||function(t,e){var i;return null!==t?(Dr[wr]=mr(t),i=new Dr,Dr[wr]=null,i[xr]=t):i=Tr(),void 0===e?i:vr.f(i,e)},Ar=!h((function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype})),Ir=z,Lr=_t,Nr=j,Rr=Ar,Fr=pi("IE_PROTO"),jr=Object,Yr=jr.prototype,Hr=Rr?jr.getPrototypeOf:function(t){var e=Nr(t);if(Ir(e,Fr))return e[Fr];var i=e.constructor;return Lr(i)&&e instanceof i?i.prototype:e instanceof jr?Yr:null},zr=ui,Br=function(t,e,i,n){return n&&n.enumerable?t[e]=i:zr(t,e,i),t},Gr=h,Wr=_t,Vr=$t,Ur=Pr,Xr=Hr,qr=Br,$r=ft("iterator"),Zr=!1;[].keys&&("next"in(Er=[].keys())?(Or=Xr(Xr(Er)))!==Object.prototype&&(Mr=Or):Zr=!0);var Kr=!Vr(Mr)||Gr((function(){var t={};return Mr[$r].call(t)!==t}));Wr((Mr=Kr?{}:Ur(Mr))[$r])||qr(Mr,$r,(function(){return this}));var Jr={IteratorPrototype:Mr,BUGGY_SAFARI_ITERATORS:Zr},Qr=Pt,to=vt?{}.toString:function(){return"[object "+Qr(this)+"]"},eo=vt,io=Kt.f,no=ui,ro=z,oo=to,so=ft("toStringTag"),ao=function(t,e,i,n){if(t){var r=i?t:t.prototype;ro(r,so)||io(r,so,{configurable:!0,value:e}),n&&!eo&&no(r,"toString",oo)}},lo={},ho=Jr.IteratorPrototype,uo=Pr,co=ai,po=ao,fo=lo,mo=function(){return this},vo=m,go=Oe,yo=_t,bo=String,_o=TypeError,wo=function(t,e,i){try{return vo(go(Object.getOwnPropertyDescriptor(t,e)[i]))}catch(t){}},ko=le,xo=function(t){if("object"==typeof t||yo(t))return t;throw new _o("Can't set "+bo(t)+" as a prototype")},Do=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,i={};try{(t=wo(Object.prototype,"__proto__","set"))(i,[]),e=i instanceof Array}catch(t){}return function(i,n){return ko(i),xo(n),e?t(i,n):i.__proto__=n,i}}():void 0),So=En,Co=de,To=Rn,Mo=function(t,e,i,n){var r=e+" Iterator";return t.prototype=uo(ho,{next:co(+!n,i)}),po(t,r,!1,!0),fo[r]=mo,t},Oo=Hr,Eo=ao,Po=Br,Ao=lo,Io=Jr,Lo=To.PROPER,No=Io.BUGGY_SAFARI_ITERATORS,Ro=ft("iterator"),Fo="keys",jo="values",Yo="entries",Ho=function(){return this},zo=function(t,e,i,n,r,o,s){Mo(i,e,n);var a,l,h,u=function(t){if(t===r&&m)return m;if(!No&&t&&t in p)return p[t];switch(t){case Fo:case jo:case Yo:return function(){return new i(this,t)}}return function(){return new i(this)}},d=e+" Iterator",c=!1,p=t.prototype,f=p[Ro]||p["@@iterator"]||r&&p[r],m=!No&&f||u(r),v="Array"===e&&p.entries||f;if(v&&(a=Oo(v.call(new t)))!==Object.prototype&&a.next&&(Eo(a,d,!0,!0),Ao[d]=Ho),Lo&&r===jo&&f&&f.name!==jo&&(c=!0,m=function(){return Co(f,this)}),r)if(l={values:u(jo),keys:o?m:u(Fo),entries:u(Yo)},s)for(h in l)(No||c||!(h in p))&&Po(p,h,l[h]);else So({target:e,proto:!0,forced:No||c},l);return s&&p[Ro]!==m&&Po(p,Ro,m,{name:r}),Ao[e]=m,l},Bo=function(t,e){return{value:t,done:e}},Go=Gt.charAt,Wo=Lt,Vo=Mi,Uo=zo,Xo=Bo,qo="String Iterator",$o=Vo.set,Zo=Vo.getterFor(qo);Uo(String,"String",(function(t){$o(this,{type:qo,string:Wo(t),index:0})}),(function(){var t,e=Zo(this),i=e.string,n=e.index;return n>=i.length?Xo(void 0,!0):(t=Go(i,n),e.index+=t.length,Xo(t,!1))}));var Ko=de,Jo=le,Qo=Ae,ts=function(t,e,i){var n,r;Jo(t);try{if(!(n=Qo(t,"return"))){if("throw"===e)throw i;return i}n=Ko(n,t)}catch(t){r=!0,n=t}if("throw"===e)throw i;if(r)throw n;return Jo(n),i},es=le,is=ts,ns=lo,rs=ft("iterator"),os=Array.prototype,ss=function(t){return void 0!==t&&(ns.Array===t||os[rs]===t)},as=_t,ls=T,hs=m(Function.toString);as(ls.inspectSource)||(ls.inspectSource=function(t){return hs(t)});var us=ls.inspectSource,ds=m,cs=h,ps=_t,fs=Pt,ms=us,vs=function(){},gs=[],ys=ge("Reflect","construct"),bs=/^\s*(?:class|function)\b/,_s=ds(bs.exec),ws=!bs.test(vs),ks=function(t){if(!ps(t))return!1;try{return ys(vs,gs,t),!0}catch(t){return!1}},xs=function(t){if(!ps(t))return!1;switch(fs(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return ws||!!_s(bs,ms(t))}catch(t){return!0}};xs.sham=!0;var Ds=!ys||cs((function(){var t;return ks(ks.call)||!ks(Object)||!ks((function(){t=!0}))||t}))?xs:ks,Ss=Ue,Cs=Kt,Ts=ai,Ms=function(t,e,i){var n=Ss(e);n in t?Cs.f(t,n,Ts(0,i)):t[n]=i},Os=Pt,Es=Ae,Ps=A,As=lo,Is=ft("iterator"),Ls=function(t){if(!Ps(t))return Es(t,Is)||Es(t,"@@iterator")||As[Os(t)]},Ns=de,Rs=Oe,Fs=le,js=Se,Ys=Ls,Hs=TypeError,zs=function(t,e){var i=arguments.length<2?Ys(t):e;if(Rs(i))return Fs(Ns(i,t));throw new Hs(js(t)+" is not iterable")},Bs=yn,Gs=de,Ws=j,Vs=function(t,e,i,n){try{return n?e(es(i)[0],i[1]):e(i)}catch(e){is(t,"throw",e)}},Us=ss,Xs=Ds,qs=Vn,$s=Ms,Zs=zs,Ks=Ls,Js=Array,Qs=ft("iterator"),ta=!1;try{var ea=0,ia={next:function(){return{done:!!ea++}},return:function(){ta=!0}};ia[Qs]=function(){return this},Array.from(ia,(function(){throw 2}))}catch(t){}var na=function(t,e){try{if(!e&&!ta)return!1}catch(t){return!1}var i=!1;try{var n={};n[Qs]=function(){return{next:function(){return{done:i=!0}}}},t(n)}catch(t){}return i},ra=function(t){var e=Ws(t),i=Xs(this),n=arguments.length,r=n>1?arguments[1]:void 0,o=void 0!==r;o&&(r=Bs(r,n>2?arguments[2]:void 0));var s,a,l,h,u,d,c=Ks(e),p=0;if(!c||this===Js&&Us(c))for(s=qs(e),a=i?new this(s):Js(s);s>p;p++)d=o?r(e[p],p):e[p],$s(a,p,d);else for(u=(h=Zs(e,c)).next,a=i?new this:[];!(l=Gs(u,h)).done;p++)d=o?Vs(h,r,[l.value,p],!0):l.value,$s(a,p,d);return a.length=p,a};En({target:"Array",stat:!0,forced:!na((function(t){Array.from(t)}))},{from:ra});var oa=ce.Array.from,sa=n(oa),aa=$i,la=lo,ha=Mi;Kt.f;var ua=zo,da=Bo,ca="Array Iterator",pa=ha.set,fa=ha.getterFor(ca);ua(Array,"Array",(function(t,e){pa(this,{type:ca,target:aa(t),index:0,kind:e})}),(function(){var t=fa(this),e=t.target,i=t.kind,n=t.index++;if(!e||n>=e.length)return t.target=void 0,da(void 0,!0);switch(i){case"keys":return da(n,!1);case"values":return da(e[n],!1)}return da([n,e[n]],!1)}),"values"),la.Arguments=la.Array;var ma=Ls,va={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},ga=w,ya=Pt,ba=ui,_a=lo,wa=ft("toStringTag");for(var ka in va){var xa=ga[ka],Da=xa&&xa.prototype;Da&&ya(Da)!==wa&&ba(Da,wa,ka),_a[ka]=_a.Array}var Sa=ma,Ca=n(Sa),Ta=n(Sa);function Ma(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var Oa={exports:{}},Ea=En,Pa=Zt,Aa=Kt.f;Ea({target:"Object",stat:!0,forced:Object.defineProperty!==Aa,sham:!Pa},{defineProperty:Aa});var Ia=ce.Object,La=Oa.exports=function(t,e,i){return Ia.defineProperty(t,e,i)};Ia.defineProperty.sham&&(La.sham=!0);var Na=Oa.exports,Ra=Na,Fa=n(Ra),ja=Dt,Ya=Array.isArray||function(t){return"Array"===ja(t)},Ha=TypeError,za=function(t){if(t>9007199254740991)throw Ha("Maximum allowed index exceeded");return t},Ba=Ya,Ga=Ds,Wa=$t,Va=ft("species"),Ua=Array,Xa=function(t){var e;return Ba(t)&&(e=t.constructor,(Ga(e)&&(e===Ua||Ba(e.prototype))||Wa(e)&&null===(e=e[Va]))&&(e=void 0)),void 0===e?Ua:e},qa=function(t,e){return new(Xa(t))(0===e?0:e)},$a=h,Za=tt,Ka=ft("species"),Ja=function(t){return Za>=51||!$a((function(){var e=[];return(e.constructor={})[Ka]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},Qa=En,tl=h,el=Ya,il=$t,nl=j,rl=Vn,ol=za,sl=Ms,al=qa,ll=Ja,hl=tt,ul=ft("isConcatSpreadable"),dl=hl>=51||!tl((function(){var t=[];return t[ul]=!1,t.concat()[0]!==t})),cl=function(t){if(!il(t))return!1;var e=t[ul];return void 0!==e?!!e:el(t)};Qa({target:"Array",proto:!0,arity:1,forced:!dl||!ll("concat")},{concat:function(t){var e,i,n,r,o,s=nl(this),a=al(s,0),l=0;for(e=-1,n=arguments.length;ey;y++)if((a||y in m)&&(p=v(c=m[y],y,f),t))if(e)_[y]=p;else if(p)switch(t){case 3:return!0;case 5:return c;case 6:return y;case 2:ql(_,c)}else switch(t){case 4:return!1;case 7:ql(_,c)}return o?-1:n||r?r:_}},Zl={forEach:$l(0),map:$l(1),filter:$l(2),some:$l(3),every:$l(4),find:$l(5),findIndex:$l(6),filterReject:$l(7)},Kl=En,Jl=w,Ql=de,th=m,eh=Zt,ih=rt,nh=h,rh=z,oh=ye,sh=le,ah=$i,lh=Ue,hh=Lt,uh=ai,dh=Pr,ch=sr,ph=pl,fh=vl,mh=Ml,vh=Fi,gh=Kt,yh=Fn,bh=ji,_h=Br,wh=El,kh=P,xh=fi,Dh=U,Sh=ft,Ch=Pl,Th=Fl,Mh=Bl,Oh=ao,Eh=Mi,Ph=Zl.forEach,Ah=pi("hidden"),Ih="Symbol",Lh="prototype",Nh=Eh.set,Rh=Eh.getterFor(Ih),Fh=Object[Lh],jh=Jl.Symbol,Yh=jh&&jh[Lh],Hh=Jl.RangeError,zh=Jl.TypeError,Bh=Jl.QObject,Gh=vh.f,Wh=gh.f,Vh=fh.f,Uh=bh.f,Xh=th([].push),qh=kh("symbols"),$h=kh("op-symbols"),Zh=kh("wks"),Kh=!Bh||!Bh[Lh]||!Bh[Lh].findChild,Jh=function(t,e,i){var n=Gh(Fh,e);n&&delete Fh[e],Wh(t,e,i),n&&t!==Fh&&Wh(Fh,e,n)},Qh=eh&&nh((function(){return 7!==dh(Wh({},"a",{get:function(){return Wh(this,"a",{value:7}).a}})).a}))?Jh:Wh,tu=function(t,e){var i=qh[t]=dh(Yh);return Nh(i,{type:Ih,tag:t,description:e}),eh||(i.description=e),i},eu=function(t,e,i){t===Fh&&eu($h,e,i),sh(t);var n=lh(e);return sh(i),rh(qh,n)?(i.enumerable?(rh(t,Ah)&&t[Ah][n]&&(t[Ah][n]=!1),i=dh(i,{enumerable:uh(0,!1)})):(rh(t,Ah)||Wh(t,Ah,uh(1,{})),t[Ah][n]=!0),Qh(t,n,i)):Wh(t,n,i)},iu=function(t,e){sh(t);var i=ah(e),n=ch(i).concat(su(i));return Ph(n,(function(e){eh&&!Ql(nu,i,e)||eu(t,e,i[e])})),t},nu=function(t){var e=lh(t),i=Ql(Uh,this,e);return!(this===Fh&&rh(qh,e)&&!rh($h,e))&&(!(i||!rh(this,e)||!rh(qh,e)||rh(this,Ah)&&this[Ah][e])||i)},ru=function(t,e){var i=ah(t),n=lh(e);if(i!==Fh||!rh(qh,n)||rh($h,n)){var r=Gh(i,n);return!r||!rh(qh,n)||rh(i,Ah)&&i[Ah][n]||(r.enumerable=!0),r}},ou=function(t){var e=Vh(ah(t)),i=[];return Ph(e,(function(t){rh(qh,t)||rh(xh,t)||Xh(i,t)})),i},su=function(t){var e=t===Fh,i=Vh(e?$h:ah(t)),n=[];return Ph(i,(function(t){!rh(qh,t)||e&&!rh(Fh,t)||Xh(n,qh[t])})),n};ih||(jh=function(){if(oh(Yh,this))throw new zh("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?hh(arguments[0]):void 0,e=Dh(t),i=function(t){this===Fh&&Ql(i,$h,t),rh(this,Ah)&&rh(this[Ah],e)&&(this[Ah][e]=!1);var n=uh(1,t);try{Qh(this,e,n)}catch(t){if(!(t instanceof Hh))throw t;Jh(this,e,n)}};return eh&&Kh&&Qh(Fh,e,{configurable:!0,set:i}),tu(e,t)},_h(Yh=jh[Lh],"toString",(function(){return Rh(this).tag})),_h(jh,"withoutSetter",(function(t){return tu(Dh(t),t)})),bh.f=nu,gh.f=eu,yh.f=iu,vh.f=ru,ph.f=fh.f=ou,mh.f=su,Ch.f=function(t){return tu(Sh(t),t)},eh&&wh(Yh,"description",{configurable:!0,get:function(){return Rh(this).description}})),Kl({global:!0,constructor:!0,wrap:!0,forced:!ih,sham:!ih},{Symbol:jh}),Ph(ch(Zh),(function(t){Th(t)})),Kl({target:Ih,stat:!0,forced:!ih},{useSetter:function(){Kh=!0},useSimple:function(){Kh=!1}}),Kl({target:"Object",stat:!0,forced:!ih,sham:!eh},{create:function(t,e){return void 0===e?dh(t):iu(dh(t),e)},defineProperty:eu,defineProperties:iu,getOwnPropertyDescriptor:ru}),Kl({target:"Object",stat:!0,forced:!ih},{getOwnPropertyNames:ou}),Mh(),Oh(jh,Ih),xh[Ah]=!0;var au=rt&&!!Symbol.for&&!!Symbol.keyFor,lu=En,hu=ge,uu=z,du=Lt,cu=P,pu=au,fu=cu("string-to-symbol-registry"),mu=cu("symbol-to-string-registry");lu({target:"Symbol",stat:!0,forced:!pu},{for:function(t){var e=du(t);if(uu(fu,e))return fu[e];var i=hu("Symbol")(e);return fu[e]=i,mu[i]=e,i}});var vu=En,gu=z,yu=xe,bu=Se,_u=au,wu=P("symbol-to-string-registry");vu({target:"Symbol",stat:!0,forced:!_u},{keyFor:function(t){if(!yu(t))throw new TypeError(bu(t)+" is not a symbol");if(gu(wu,t))return wu[t]}});var ku=m([].slice),xu=Ya,Du=_t,Su=Dt,Cu=Lt,Tu=m([].push),Mu=En,Ou=ge,Eu=Ii,Pu=de,Au=m,Iu=h,Lu=_t,Nu=xe,Ru=ku,Fu=function(t){if(Du(t))return t;if(xu(t)){for(var e=t.length,i=[],n=0;nt.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?arguments[1]:void 0)}});var Zc=Jd("Array").map,Kc=ye,Jc=Zc,Qc=Array.prototype,tp=function(t){var e=t.map;return t===Qc||Kc(Qc,t)&&e===Qc.map?Jc:e},ep=n(tp),ip=j,np=sr;En({target:"Object",stat:!0,forced:h((function(){np(1)}))},{keys:function(t){return np(ip(t))}});var rp=n(ce.Object.keys),op=En,sp=Date,ap=m(sp.prototype.getTime);op({target:"Date",stat:!0},{now:function(){return ap(new sp)}});var lp=n(ce.Date.now),hp=m,up=Oe,dp=$t,cp=z,pp=ku,fp=u,mp=Function,vp=hp([].concat),gp=hp([].join),yp={},bp=fp?mp.bind:function(t){var e=up(this),i=e.prototype,n=pp(arguments,1),r=function(){var i=vp(n,pp(arguments));return this instanceof r?function(t,e,i){if(!cp(yp,e)){for(var n=[],r=0;r1?arguments[1]:void 0)};En({target:"Array",proto:!0,forced:[].forEach!==Pp},{forEach:Pp});var Ap=Jd("Array").forEach,Ip=Pt,Lp=z,Np=ye,Rp=Ap,Fp=Array.prototype,jp={DOMTokenList:!0,NodeList:!0},Yp=function(t){var e=t.forEach;return t===Fp||Np(Fp,t)&&e===Fp.forEach||Lp(jp,Ip(t))?Rp:e},Hp=n(Yp),zp=En,Bp=Ya,Gp=m([].reverse),Wp=[1,2];zp({target:"Array",proto:!0,forced:String(Wp)===String(Wp.reverse())},{reverse:function(){return Bp(this)&&(this.length=this.length),Gp(this)}});var Vp=Jd("Array").reverse,Up=ye,Xp=Vp,qp=Array.prototype,$p=function(t){var e=t.reverse;return t===qp||Up(qp,t)&&e===qp.reverse?Xp:e},Zp=$p,Kp=n(Zp),Jp=Se,Qp=TypeError,tf=function(t,e){if(!delete t[e])throw new Qp("Cannot delete property "+Jp(e)+" of "+Jp(t))},ef=En,nf=j,rf=zn,of=b,sf=Vn,af=Ud,lf=za,hf=qa,uf=Ms,df=tf,cf=Ja("splice"),pf=Math.max,ff=Math.min;ef({target:"Array",proto:!0,forced:!cf},{splice:function(t,e){var i,n,r,o,s,a,l=nf(this),h=sf(l),u=rf(t,h),d=arguments.length;for(0===d?i=n=0:1===d?(i=0,n=h-u):(i=d-2,n=ff(pf(of(e),0),h-u)),lf(h+i-n),r=hf(l,n),o=0;oh-n+i;o--)df(l,o-1)}else if(i>n)for(o=h-n;o>u;o--)a=o+i-1,(s=o+n-1)in l?l[a]=l[s]:df(l,a);for(o=0;or;)for(var a,l=Of(arguments[r++]),h=o?Af(Sf(l),o(l)):Sf(l),u=h.length,d=0;u>d;)a=h[d++],wf&&!xf(s,l,a)||(i[a]=l[a]);return i}:Ef,Lf=If;En({target:"Object",stat:!0,arity:2,forced:Object.assign!==Lf},{assign:Lf});var Nf=n(ce.Object.assign),Rf=Zn.includes;En({target:"Array",proto:!0,forced:h((function(){return!Array(1).includes()}))},{includes:function(t){return Rf(this,t,arguments.length>1?arguments[1]:void 0)}});var Ff=Jd("Array").includes,jf=$t,Yf=Dt,Hf=ft("match"),zf=function(t){var e;return jf(t)&&(void 0!==(e=t[Hf])?!!e:"RegExp"===Yf(t))},Bf=TypeError,Gf=ft("match"),Wf=En,Vf=function(t){if(zf(t))throw new Bf("The method doesn't accept regular expressions");return t},Uf=N,Xf=Lt,qf=function(t){var e=/./;try{"/./"[t](e)}catch(i){try{return e[Gf]=!1,"/./"[t](e)}catch(t){}}return!1},$f=m("".indexOf);Wf({target:"String",proto:!0,forced:!qf("includes")},{includes:function(t){return!!~$f(Xf(Uf(this)),Xf(Vf(t)),arguments.length>1?arguments[1]:void 0)}});var Zf=Jd("String").includes,Kf=ye,Jf=Ff,Qf=Zf,tm=Array.prototype,em=String.prototype,im=function(t){var e=t.includes;return t===tm||Kf(tm,t)&&e===tm.includes?Jf:"string"==typeof t||t===em||Kf(em,t)&&e===em.includes?Qf:e},nm=n(im),rm=j,om=Hr,sm=Ar;En({target:"Object",stat:!0,forced:h((function(){om(1)})),sham:!sm},{getPrototypeOf:function(t){return om(rm(t))}});var am=ce.Object.getPrototypeOf,lm=n(am),hm=Zl.filter;En({target:"Array",proto:!0,forced:!Ja("filter")},{filter:function(t){return hm(this,t,arguments.length>1?arguments[1]:void 0)}});var um=Jd("Array").filter,dm=ye,cm=um,pm=Array.prototype,fm=function(t){var e=t.filter;return t===pm||dm(pm,t)&&e===pm.filter?cm:e},mm=n(fm),vm=Zt,gm=h,ym=m,bm=Hr,_m=sr,wm=$i,km=ym(ji.f),xm=ym([].push),Dm=vm&&gm((function(){var t=Object.create(null);return t[2]=2,!km(t,2)})),Sm=function(t){return function(e){for(var i,n=wm(e),r=_m(n),o=Dm&&null===bm(n),s=r.length,a=0,l=[];s>a;)i=r[a++],vm&&!(o?i in n:km(n,i))||xm(l,t?[i,n[i]]:n[i]);return l}},Cm={entries:Sm(!0),values:Sm(!1)},Tm=Cm.values;En({target:"Object",stat:!0},{values:function(t){return Tm(t)}});var Mm=n(ce.Object.values),Om="\t\n\v\f\r                 \u2028\u2029\ufeff",Em=N,Pm=Lt,Am=Om,Im=m("".replace),Lm=RegExp("^["+Am+"]+"),Nm=RegExp("(^|[^"+Am+"])["+Am+"]+$"),Rm=function(t){return function(e){var i=Pm(Em(e));return 1&t&&(i=Im(i,Lm,"")),2&t&&(i=Im(i,Nm,"$1")),i}},Fm={start:Rm(1),end:Rm(2),trim:Rm(3)},jm=w,Ym=h,Hm=m,zm=Lt,Bm=Fm.trim,Gm=Om,Wm=jm.parseInt,Vm=jm.Symbol,Um=Vm&&Vm.iterator,Xm=/^[+-]?0x/i,qm=Hm(Xm.exec),$m=8!==Wm(Gm+"08")||22!==Wm(Gm+"0x16")||Um&&!Ym((function(){Wm(Object(Um))}))?function(t,e){var i=Bm(zm(t));return Wm(i,e>>>0||(qm(Xm,i)?16:10))}:Wm;En({global:!0,forced:parseInt!==$m},{parseInt:$m});var Zm=n(ce.parseInt),Km=En,Jm=Zn.indexOf,Qm=Op,tv=Ri([].indexOf),ev=!!tv&&1/tv([1],1,-0)<0;Km({target:"Array",proto:!0,forced:ev||!Qm("indexOf")},{indexOf:function(t){var e=arguments.length>1?arguments[1]:void 0;return ev?tv(this,t,e)||0:Jm(this,t,e)}});var iv=Jd("Array").indexOf,nv=ye,rv=iv,ov=Array.prototype,sv=function(t){var e=t.indexOf;return t===ov||nv(ov,t)&&e===ov.indexOf?rv:e},av=n(sv),lv=Cm.entries;En({target:"Object",stat:!0},{entries:function(t){return lv(t)}});var hv=n(ce.Object.entries);En({target:"Object",stat:!0,sham:!Zt},{create:Pr});var uv=ce.Object,dv=function(t,e){return uv.create(t,e)},cv=n(dv),pv=ce,fv=Ii;pv.JSON||(pv.JSON={stringify:JSON.stringify});var mv=function(t,e,i){return fv(pv.JSON.stringify,null,arguments)},vv=n(mv),gv="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,yv=TypeError,bv=function(t,e){if(ti,s=kv(n)?n:Tv(n),a=o?Sv(arguments,i):[],l=o?function(){wv(s,this,a)}:s;return e?t(l,r):t(l)}:t},Ev=En,Pv=w,Av=Ov(Pv.setInterval,!0);Ev({global:!0,bind:!0,forced:Pv.setInterval!==Av},{setInterval:Av});var Iv=En,Lv=w,Nv=Ov(Lv.setTimeout,!0);Iv({global:!0,bind:!0,forced:Lv.setTimeout!==Nv},{setTimeout:Nv});var Rv=n(ce.setTimeout),Fv=j,jv=zn,Yv=Vn,Hv=function(t){for(var e=Fv(this),i=Yv(e),n=arguments.length,r=jv(n>1?arguments[1]:void 0,i),o=n>2?arguments[2]:void 0,s=void 0===o?i:jv(o,i);s>r;)e[r++]=t;return e};En({target:"Array",proto:!0},{fill:Hv});var zv=Jd("Array").fill,Bv=ye,Gv=zv,Wv=Array.prototype,Vv=function(t){var e=t.fill;return t===Wv||Bv(Wv,t)&&e===Wv.fill?Gv:e},Uv=n(Vv),Xv={exports:{}};!function(t){function e(t){if(t)return function(t){for(var i in e.prototype)t[i]=e.prototype[i];return t}(t)}t.exports=e,e.prototype.on=e.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},e.prototype.once=function(t,e){function i(){this.off(t,i),e.apply(this,arguments)}return i.fn=e,this.on(t,i),this},e.prototype.off=e.prototype.removeListener=e.prototype.removeAllListeners=e.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var i,n=this._callbacks["$"+t];if(!n)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var r=0;r-1}var t_=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===Db&&(t=this.compute()),xb&&this.manager.element.style&&Eb[t]&&(this.manager.element.style[kb]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return Kb(this.manager.recognizers,(function(e){Jb(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(Qb(t,Tb))return Tb;var e=Qb(t,Mb),i=Qb(t,Ob);return e&&i?Tb:e||i?e?Mb:Ob:Qb(t,Cb)?Cb:Sb}(t.join(" "))},e.preventDefaults=function(t){var e=t.srcEvent,i=t.offsetDirection;if(this.manager.session.prevented)e.preventDefault();else{var n=this.actions,r=Qb(n,Tb)&&!Eb[Tb],o=Qb(n,Ob)&&!Eb[Ob],s=Qb(n,Mb)&&!Eb[Mb];if(r){var a=1===t.pointers.length,l=t.distance<2,h=t.deltaTime<250;if(a&&l&&h)return}if(!s||!o)return r||o&&i&Ub||s&&i&Xb?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function e_(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function i_(t){var e=t.length;if(1===e)return{x:yb(t[0].clientX),y:yb(t[0].clientY)};for(var i=0,n=0,r=0;r=bb(e)?t<0?Bb:Gb:e<0?Wb:Vb}function a_(t,e,i){return{x:e/t||0,y:i/t||0}}function l_(t,e){var i=t.session,n=e.pointers,r=n.length;i.firstInput||(i.firstInput=n_(e)),r>1&&!i.firstMultiple?i.firstMultiple=n_(e):1===r&&(i.firstMultiple=!1);var o=i.firstInput,s=i.firstMultiple,a=s?s.center:o.center,l=e.center=i_(n);e.timeStamp=_b(),e.deltaTime=e.timeStamp-o.timeStamp,e.angle=o_(a,l),e.distance=r_(a,l),function(t,e){var i=e.center,n=t.offsetDelta||{},r=t.prevDelta||{},o=t.prevInput||{};e.eventType!==Fb&&o.eventType!==Yb||(r=t.prevDelta={x:o.deltaX||0,y:o.deltaY||0},n=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=r.x+(i.x-n.x),e.deltaY=r.y+(i.y-n.y)}(i,e),e.offsetDirection=s_(e.deltaX,e.deltaY);var h,u,c=a_(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=c.x,e.overallVelocityY=c.y,e.overallVelocity=bb(c.x)>bb(c.y)?c.x:c.y,e.scale=s?(h=s.pointers,r_((u=n)[0],u[1],Zb)/r_(h[0],h[1],Zb)):1,e.rotation=s?function(t,e){return o_(e[1],e[0],Zb)+o_(t[1],t[0],Zb)}(s.pointers,n):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,n,r,o,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==Hb&&(a>Rb||void 0===s.velocity)){var l=e.deltaX-s.deltaX,h=e.deltaY-s.deltaY,u=a_(a,l,h);n=u.x,r=u.y,i=bb(u.x)>bb(u.y)?u.x:u.y,o=s_(l,h),t.lastInterval=e}else i=s.velocity,n=s.velocityX,r=s.velocityY,o=s.direction;e.velocity=i,e.velocityX=n,e.velocityY=r,e.direction=o}(i,e);var d,p=t.element,f=e.srcEvent;e_(d=f.composedPath?f.composedPath()[0]:f.path?f.path[0]:f.target,p)&&(p=d),e.target=p}function h_(t,e,i){var n=i.pointers.length,r=i.changedPointers.length,o=e&Fb&&n-r==0,s=e&(Yb|Hb)&&n-r==0;i.isFirst=!!o,i.isFinal=!!s,o&&(t.session={}),i.eventType=e,l_(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function u_(t){return t.trim().split(/\s+/g)}function c_(t,e,i){Kb(u_(e),(function(e){t.addEventListener(e,i,!1)}))}function d_(t,e,i){Kb(u_(e),(function(e){t.removeEventListener(e,i,!1)}))}function p_(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var f_=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){Jb(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&c_(this.element,this.evEl,this.domHandler),this.evTarget&&c_(this.target,this.evTarget,this.domHandler),this.evWin&&c_(p_(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&d_(this.element,this.evEl,this.domHandler),this.evTarget&&d_(this.target,this.evTarget,this.domHandler),this.evWin&&d_(p_(this.element),this.evWin,this.domHandler)},t}();function m_(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var n=0;ni[e]})):n.sort()),n}var x_={touchstart:Fb,touchmove:jb,touchend:Yb,touchcancel:Hb},D_="touchstart touchmove touchend touchcancel",S_=function(t){function e(){var i;return e.prototype.evTarget=D_,(i=t.apply(this,arguments)||this).targetIds={},i}return cb(e,t),e.prototype.handler=function(t){var e=x_[t.type],i=C_.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:Lb,srcEvent:t})},e}(f_);function C_(t,e){var i,n,r=w_(t.touches),o=this.targetIds;if(e&(Fb|jb)&&1===r.length)return o[r[0].identifier]=!0,[r,r];var s=w_(t.changedTouches),a=[],l=this.target;if(n=r.filter((function(t){return e_(t.target,l)})),e===Fb)for(i=0;i-1&&n.splice(t,1)}),P_)}}function L_(t,e){t&Fb?(this.primaryTouch=e.changedPointers[0].identifier,A_.call(this,e)):t&(Yb|Hb)&&A_.call(this,e)}function N_(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,n=0;n-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function n(i){e.manager.emit(i,t)}i=z_&&n(e.options.event+X_(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=W_},e.canEmit=function(){for(var t=0;te.threshold&&r&e.direction},i.attrTest=function(t){return Z_.prototype.attrTest.call(this,t)&&(this.state&Y_||!(this.state&Y_)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=K_(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}(Z_),Q_=function(t){function e(e){return void 0===e&&(e={}),t.call(this,ub({event:"swipe",threshold:10,velocity:.3,direction:Ub|Xb,pointers:1},e))||this}cb(e,t);var i=e.prototype;return i.getTouchAction=function(){return J_.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,n=this.options.direction;return n&(Ub|Xb)?i=e.overallVelocity:n&Ub?i=e.overallVelocityX:n&Xb&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&n&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&bb(i)>this.options.velocity&&e.eventType&Yb},i.emit=function(t){var e=K_(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}(Z_),tw=function(t){function e(e){return void 0===e&&(e={}),t.call(this,ub({event:"pinch",threshold:0,pointers:2},e))||this}cb(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Tb]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||this.state&Y_)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}(Z_),ew=function(t){function e(e){return void 0===e&&(e={}),t.call(this,ub({event:"rotate",threshold:0,pointers:2},e))||this}cb(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Tb]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||this.state&Y_)},e}(Z_),iw=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,ub({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}cb(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Sb]},i.process=function(t){var e=this,i=this.options,n=t.pointers.length===i.pointers,r=t.distancei.time;if(this._input=t,!r||!n||t.eventType&(Yb|Hb)&&!o)this.reset();else if(t.eventType&Fb)this.reset(),this._timer=setTimeout((function(){e.state=B_,e.tryEmit()}),i.time);else if(t.eventType&Yb)return B_;return W_},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){this.state===B_&&(t&&t.eventType&Yb?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=_b(),this.manager.emit(this.options.event,this._input)))},e}(q_),nw={domEvents:!1,touchAction:Db,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},rw=[[ew,{enable:!1}],[tw,{enable:!1},["rotate"]],[Q_,{direction:Ub}],[J_,{direction:Ub},["swipe"]],[$_],[$_,{event:"doubletap",taps:2},["tap"]],[iw]];function ow(t,e){var i,n=t.element;n.style&&(Kb(t.options.cssProps,(function(r,o){i=wb(n.style,o),e?(t.oldCssProps[i]=n.style[i],n.style[i]=r):n.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var sw=function(){function t(t,e){var i,n=this;this.options=fb({},nw,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||(Ib?__:Ab?S_:Pb?R_:E_))(i,h_),this.touchAction=new t_(this,this.options.touchAction),ow(this,!0),Kb(this.options.recognizers,(function(t){var e=n.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return fb(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var n=this.recognizers,r=e.curRecognizer;(!r||r&&r.state&B_)&&(e.curRecognizer=null,r=null);for(var o=0;o\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",r=window.console&&(window.console.warn||window.console.log);return r&&r.call(window.console,n,i),t.apply(this,arguments)}}var pw=dw((function(t,e,i){for(var n=Object.keys(e),r=0;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function kw(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?i-1:0),r=1;r2)return Cw.apply(void 0,Up(n=[Sw(e[0],e[1])]).call(n,Np(qp(e).call(e,2))));var r,o=e[0],s=e[1],a=ww(Jp(s));try{for(a.s();!(r=a.n()).done;){var l=r.value;Object.prototype.propertyIsEnumerable.call(s,l)&&(s[l]===xw?delete o[l]:null===o[l]||null===s[l]||"object"!==Nd(o[l])||"object"!==Nd(s[l])||tf(o[l])||tf(s[l])?o[l]=Tw(s[l]):o[l]=Cw(o[l],s[l]))}}catch(t){a.e(t)}finally{a.f()}return o}function Tw(t){return tf(t)?cf(t).call(t,(function(t){return Tw(t)})):"object"===Nd(t)&&null!==t?Cw({},t):t}function Mw(t){for(var e=0,i=gf(t);e2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r)||!0===i)if("object"===Nd(e[r])&&null!==e[r]&&Uv(e[r])===Object.prototype)void 0===t[r]?t[r]=zw({},e[r],i):"object"===Nd(t[r])&&null!==t[r]&&Uv(t[r])===Object.prototype?zw(t[r],e[r],i):Yw(t,e,r,n);else if(tf(e[r])){var o;t[r]=qp(o=e[r]).call(o)}else Yw(t,e,r,n);return t}function Bw(t){var e=Nd(t);return"object"===e?null===t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":tf(t)?"Array":t instanceof Date?"Date":"Object":"number"===e?"Number":"boolean"===e?"Boolean":"string"===e?"String":void 0===e?"undefined":e}function Gw(t,e){var i;return Up(i=[]).call(i,Np(t),[e])}function Ww(t){return qp(t).call(t)}var Vw=fg;var Uw={asBoolean:function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},asNumber:function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},asString:function(t,e){return"function"==typeof t&&(t=t()),null!=t?String(t):e||null},asSize:function(t,e){return"function"==typeof t&&(t=t()),Fw(t)?t:Rw(t)?t+"px":e||null},asElement:function(t,e){return"function"==typeof t&&(t=t()),t||e||null}};function Xw(t){var e;switch(t.length){case 3:case 4:return(e=Aw.exec(t))?{r:Yg(e[1]+e[1],16),g:Yg(e[2]+e[2],16),b:Yg(e[3]+e[3],16)}:null;case 6:case 7:return(e=Iw.exec(t))?{r:Yg(e[1],16),g:Yg(e[2],16),b:Yg(e[3],16)}:null;default:return null}}function qw(t,e,i){var n;return"#"+qp(n=((1<<24)+(t<<16)+(e<<8)+i).toString(16)).call(n,1)}function $w(t,e,i){t/=255,e/=255,i/=255;var n=Math.min(t,Math.min(e,i)),r=Math.max(t,Math.max(e,i));return n===r?{h:0,s:0,v:n}:{h:60*((t===n?3:i===n?1:5)-(t===n?e-i:i===n?t-e:i-t)/(r-n))/360,s:(r-n)/r,v:r}}var Zw={split:function(t){var e,i={};return am(e=t.split(";")).call(e,(function(t){if(""!=dy(t).call(t)){var e,n,r=t.split(":"),o=dy(e=r[0]).call(e),s=dy(n=r[1]).call(n);i[o]=s}})),i},join:function(t){var e;return cf(e=gf(t)).call(e,(function(e){return e+": "+t[e]})).join("; ")}};function Kw(t,e,i){var n,r,o,s=Math.floor(6*t),a=6*t-s,l=i*(1-e),h=i*(1-a*e),u=i*(1-(1-a)*e);switch(s%6){case 0:n=i,r=u,o=l;break;case 1:n=h,r=i,o=l;break;case 2:n=l,r=i,o=u;break;case 3:n=l,r=h,o=i;break;case 4:n=u,r=l,o=i;break;case 5:n=i,r=l,o=h}return{r:Math.floor(255*n),g:Math.floor(255*r),b:Math.floor(255*o)}}function Jw(t,e,i){var n=Kw(t,e,i);return qw(n.r,n.g,n.b)}function Qw(t){var e=Xw(t);if(!e)throw new TypeError("'".concat(t,"' is not a valid color."));return $w(e.r,e.g,e.b)}function tk(t){return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(t)}function ek(t){return Lw.test(t)}function ik(t){return Nw.test(t)}function nk(t){if(null===t||"object"!==Nd(t))return null;if(t instanceof Element)return t;var e=gy(t);for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&"object"==Nd(t[i])&&(e[i]=nk(t[i]));return e}var rk={black:"#000000",navy:"#000080",darkblue:"#00008B",mediumblue:"#0000CD",blue:"#0000FF",darkgreen:"#006400",green:"#008000",teal:"#008080",darkcyan:"#008B8B",deepskyblue:"#00BFFF",darkturquoise:"#00CED1",mediumspringgreen:"#00FA9A",lime:"#00FF00",springgreen:"#00FF7F",aqua:"#00FFFF",cyan:"#00FFFF",midnightblue:"#191970",dodgerblue:"#1E90FF",lightseagreen:"#20B2AA",forestgreen:"#228B22",seagreen:"#2E8B57",darkslategray:"#2F4F4F",limegreen:"#32CD32",mediumseagreen:"#3CB371",turquoise:"#40E0D0",royalblue:"#4169E1",steelblue:"#4682B4",darkslateblue:"#483D8B",mediumturquoise:"#48D1CC",indigo:"#4B0082",darkolivegreen:"#556B2F",cadetblue:"#5F9EA0",cornflowerblue:"#6495ED",mediumaquamarine:"#66CDAA",dimgray:"#696969",slateblue:"#6A5ACD",olivedrab:"#6B8E23",slategray:"#708090",lightslategray:"#778899",mediumslateblue:"#7B68EE",lawngreen:"#7CFC00",chartreuse:"#7FFF00",aquamarine:"#7FFFD4",maroon:"#800000",purple:"#800080",olive:"#808000",gray:"#808080",skyblue:"#87CEEB",lightskyblue:"#87CEFA",blueviolet:"#8A2BE2",darkred:"#8B0000",darkmagenta:"#8B008B",saddlebrown:"#8B4513",darkseagreen:"#8FBC8F",lightgreen:"#90EE90",mediumpurple:"#9370D8",darkviolet:"#9400D3",palegreen:"#98FB98",darkorchid:"#9932CC",yellowgreen:"#9ACD32",sienna:"#A0522D",brown:"#A52A2A",darkgray:"#A9A9A9",lightblue:"#ADD8E6",greenyellow:"#ADFF2F",paleturquoise:"#AFEEEE",lightsteelblue:"#B0C4DE",powderblue:"#B0E0E6",firebrick:"#B22222",darkgoldenrod:"#B8860B",mediumorchid:"#BA55D3",rosybrown:"#BC8F8F",darkkhaki:"#BDB76B",silver:"#C0C0C0",mediumvioletred:"#C71585",indianred:"#CD5C5C",peru:"#CD853F",chocolate:"#D2691E",tan:"#D2B48C",lightgrey:"#D3D3D3",palevioletred:"#D87093",thistle:"#D8BFD8",orchid:"#DA70D6",goldenrod:"#DAA520",crimson:"#DC143C",gainsboro:"#DCDCDC",plum:"#DDA0DD",burlywood:"#DEB887",lightcyan:"#E0FFFF",lavender:"#E6E6FA",darksalmon:"#E9967A",violet:"#EE82EE",palegoldenrod:"#EEE8AA",lightcoral:"#F08080",khaki:"#F0E68C",aliceblue:"#F0F8FF",honeydew:"#F0FFF0",azure:"#F0FFFF",sandybrown:"#F4A460",wheat:"#F5DEB3",beige:"#F5F5DC",whitesmoke:"#F5F5F5",mintcream:"#F5FFFA",ghostwhite:"#F8F8FF",salmon:"#FA8072",antiquewhite:"#FAEBD7",linen:"#FAF0E6",lightgoldenrodyellow:"#FAFAD2",oldlace:"#FDF5E6",red:"#FF0000",fuchsia:"#FF00FF",magenta:"#FF00FF",deeppink:"#FF1493",orangered:"#FF4500",tomato:"#FF6347",hotpink:"#FF69B4",coral:"#FF7F50",darkorange:"#FF8C00",lightsalmon:"#FFA07A",orange:"#FFA500",lightpink:"#FFB6C1",pink:"#FFC0CB",gold:"#FFD700",peachpuff:"#FFDAB9",navajowhite:"#FFDEAD",moccasin:"#FFE4B5",bisque:"#FFE4C4",mistyrose:"#FFE4E1",blanchedalmond:"#FFEBCD",papayawhip:"#FFEFD5",lavenderblush:"#FFF0F5",seashell:"#FFF5EE",cornsilk:"#FFF8DC",lemonchiffon:"#FFFACD",floralwhite:"#FFFAF0",snow:"#FFFAFA",yellow:"#FFFF00",lightyellow:"#FFFFE0",ivory:"#FFFFF0",white:"#FFFFFF"},ok=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;Sc(this,t),this.pixelRatio=e,this.generated=!1,this.centerCoordinates={x:144.5,y:144.5},this.r=289*.49,this.color={r:255,g:255,b:255,a:1},this.hueCircle=void 0,this.initialColor={r:255,g:255,b:255,a:1},this.previousColor=void 0,this.applied=!1,this.updateCallback=function(){},this.closeCallback=function(){},this._create()}return Wd(t,[{key:"insertTo",value:function(t){void 0!==this.hammer&&(this.hammer.destroy(),this.hammer=void 0),this.container=t,this.container.appendChild(this.frame),this._bindHammer(),this._setSize()}},{key:"setUpdateCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker update callback is not a function.");this.updateCallback=t}},{key:"setCloseCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker closing callback is not a function.");this.closeCallback=t}},{key:"_isColorString",value:function(t){if("string"==typeof t)return rk[t]}},{key:"setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if("none"!==t){var i,n=this._isColorString(t);if(void 0!==n&&(t=n),!0===Fw(t)){if(!0===ek(t)){var r=t.substr(4).substr(0,t.length-5).split(",");i={r:r[0],g:r[1],b:r[2],a:1}}else if(!0===ik(t)){var o=t.substr(5).substr(0,t.length-6).split(",");i={r:o[0],g:o[1],b:o[2],a:o[3]}}else if(!0===tk(t)){var s=Xw(t);i={r:s.r,g:s.g,b:s.b,a:1}}}else if(t instanceof Object&&void 0!==t.r&&void 0!==t.g&&void 0!==t.b){var a=void 0!==t.a?t.a:"1.0";i={r:t.r,g:t.g,b:t.b,a:a}}if(void 0===i)throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: "+Dy(t));this._setColor(i,e)}}},{key:"show",value:function(){void 0!==this.closeCallback&&(this.closeCallback(),this.closeCallback=void 0),this.applied=!1,this.frame.style.display="block",this._generateHueCircle()}},{key:"_hide",value:function(){var t=this;!0===(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&(this.previousColor=fv({},this.color)),!0===this.applied&&this.updateCallback(this.initialColor),this.frame.style.display="none",Xy((function(){void 0!==t.closeCallback&&(t.closeCallback(),t.closeCallback=void 0)}),0)}},{key:"_save",value:function(){this.updateCallback(this.color),this.applied=!1,this._hide()}},{key:"_apply",value:function(){this.applied=!0,this.updateCallback(this.color),this._updatePicker(this.color)}},{key:"_loadLast",value:function(){void 0!==this.previousColor?this.setColor(this.previousColor,!1):alert("There is no last color to load...")}},{key:"_setColor",value:function(t){!0===(!(arguments.length>1&&void 0!==arguments[1])||arguments[1])&&(this.initialColor=fv({},t)),this.color=t;var e=$w(t.r,t.g,t.b),i=2*Math.PI,n=this.r*e.s,r=this.centerCoordinates.x+n*Math.sin(i*e.h),o=this.centerCoordinates.y+n*Math.cos(i*e.h);this.colorPickerSelector.style.left=r-.5*this.colorPickerSelector.clientWidth+"px",this.colorPickerSelector.style.top=o-.5*this.colorPickerSelector.clientHeight+"px",this._updatePicker(t)}},{key:"_setOpacity",value:function(t){this.color.a=t/100,this._updatePicker(this.color)}},{key:"_setBrightness",value:function(t){var e=$w(this.color.r,this.color.g,this.color.b);e.v=t/100;var i=Kw(e.h,e.s,e.v);i.a=this.color.a,this.color=i,this._updatePicker()}},{key:"_updatePicker",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.color,e=$w(t.r,t.g,t.b),i=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1)),i.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var n=this.colorPickerCanvas.clientWidth,r=this.colorPickerCanvas.clientHeight;i.clearRect(0,0,n,r),i.putImageData(this.hueCircle,0,0),i.fillStyle="rgba(0,0,0,"+(1-e.v)+")",i.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),sb(i).call(i),this.brightnessRange.value=100*e.v,this.opacityRange.value=100*t.a,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}},{key:"_setSize",value:function(){this.colorPickerCanvas.style.width="100%",this.colorPickerCanvas.style.height="100%",this.colorPickerCanvas.width=289*this.pixelRatio,this.colorPickerCanvas.height=289*this.pixelRatio}},{key:"_create",value:function(){var t,e,i,n;if(this.frame=document.createElement("div"),this.frame.className="vis-color-picker",this.colorPickerDiv=document.createElement("div"),this.colorPickerSelector=document.createElement("div"),this.colorPickerSelector.className="vis-selector",this.colorPickerDiv.appendChild(this.colorPickerSelector),this.colorPickerCanvas=document.createElement("canvas"),this.colorPickerDiv.appendChild(this.colorPickerCanvas),this.colorPickerCanvas.getContext){var r=this.colorPickerCanvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(r.webkitBackingStorePixelRatio||r.mozBackingStorePixelRatio||r.msBackingStorePixelRatio||r.oBackingStorePixelRatio||r.backingStorePixelRatio||1),this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var o=document.createElement("DIV");o.style.color="red",o.style.fontWeight="bold",o.style.padding="10px",o.innerText="Error: your browser does not support HTML canvas",this.colorPickerCanvas.appendChild(o)}this.colorPickerDiv.className="vis-color",this.opacityDiv=document.createElement("div"),this.opacityDiv.className="vis-opacity",this.brightnessDiv=document.createElement("div"),this.brightnessDiv.className="vis-brightness",this.arrowDiv=document.createElement("div"),this.arrowDiv.className="vis-arrow",this.opacityRange=document.createElement("input");try{this.opacityRange.type="range",this.opacityRange.min="0",this.opacityRange.max="100"}catch(t){}this.opacityRange.value="100",this.opacityRange.className="vis-range",this.brightnessRange=document.createElement("input");try{this.brightnessRange.type="range",this.brightnessRange.min="0",this.brightnessRange.max="100"}catch(t){}this.brightnessRange.value="100",this.brightnessRange.className="vis-range",this.opacityDiv.appendChild(this.opacityRange),this.brightnessDiv.appendChild(this.brightnessRange);var s=this;this.opacityRange.onchange=function(){s._setOpacity(this.value)},this.opacityRange.oninput=function(){s._setOpacity(this.value)},this.brightnessRange.onchange=function(){s._setBrightness(this.value)},this.brightnessRange.oninput=function(){s._setBrightness(this.value)},this.brightnessLabel=document.createElement("div"),this.brightnessLabel.className="vis-label vis-brightness",this.brightnessLabel.innerText="brightness:",this.opacityLabel=document.createElement("div"),this.opacityLabel.className="vis-label vis-opacity",this.opacityLabel.innerText="opacity:",this.newColorDiv=document.createElement("div"),this.newColorDiv.className="vis-new-color",this.newColorDiv.innerText="new",this.initialColorDiv=document.createElement("div"),this.initialColorDiv.className="vis-initial-color",this.initialColorDiv.innerText="initial",this.cancelButton=document.createElement("div"),this.cancelButton.className="vis-button vis-cancel",this.cancelButton.innerText="cancel",this.cancelButton.onclick=Uf(t=this._hide).call(t,this,!1),this.applyButton=document.createElement("div"),this.applyButton.className="vis-button vis-apply",this.applyButton.innerText="apply",this.applyButton.onclick=Uf(e=this._apply).call(e,this),this.saveButton=document.createElement("div"),this.saveButton.className="vis-button vis-save",this.saveButton.innerText="save",this.saveButton.onclick=Uf(i=this._save).call(i,this),this.loadButton=document.createElement("div"),this.loadButton.className="vis-button vis-load",this.loadButton.innerText="load last",this.loadButton.onclick=Uf(n=this._loadLast).call(n,this),this.frame.appendChild(this.colorPickerDiv),this.frame.appendChild(this.arrowDiv),this.frame.appendChild(this.brightnessLabel),this.frame.appendChild(this.brightnessDiv),this.frame.appendChild(this.opacityLabel),this.frame.appendChild(this.opacityDiv),this.frame.appendChild(this.newColorDiv),this.frame.appendChild(this.initialColorDiv),this.frame.appendChild(this.cancelButton),this.frame.appendChild(this.applyButton),this.frame.appendChild(this.saveButton),this.frame.appendChild(this.loadButton)}},{key:"_bindHammer",value:function(){var t=this;this.drag={},this.pinch={},this.hammer=new Ow(this.colorPickerCanvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.on("hammer.input",(function(e){e.isFirst&&t._moveSelector(e)})),this.hammer.on("tap",(function(e){t._moveSelector(e)})),this.hammer.on("panstart",(function(e){t._moveSelector(e)})),this.hammer.on("panmove",(function(e){t._moveSelector(e)})),this.hammer.on("panend",(function(e){t._moveSelector(e)}))}},{key:"_generateHueCircle",value:function(){if(!1===this.generated){var t=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var e,i,n,r,o=this.colorPickerCanvas.clientWidth,s=this.colorPickerCanvas.clientHeight;t.clearRect(0,0,o,s),this.centerCoordinates={x:.5*o,y:.5*s},this.r=.49*o;var a,l=2*Math.PI/360,h=1/this.r;for(n=0;n<360;n++)for(r=0;r3&&void 0!==arguments[3]?arguments[3]:1,o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:function(){return!1};Sc(this,t),this.parent=e,this.changedOptions=[],this.container=i,this.allowCreation=!1,this.hideOption=o,this.options={},this.initialized=!1,this.popupCounter=0,this.defaultOptions={enabled:!1,filter:!0,container:void 0,showButton:!0},fv(this.options,this.defaultOptions),this.configureOptions=n,this.moduleOptions={},this.domElements=[],this.popupDiv={},this.popupLimit=5,this.popupHistory={},this.colorPicker=new ok(r),this.wrapper=void 0}return Wd(t,[{key:"setOptions",value:function(t){if(void 0!==t){this.popupHistory={},this._removePopup();var e=!0;if("string"==typeof t)this.options.filter=t;else if(tf(t))this.options.filter=t.join();else if("object"===Nd(t)){if(null==t)throw new TypeError("options cannot be null");void 0!==t.container&&(this.options.container=t.container),void 0!==ig(t)&&(this.options.filter=ig(t)),void 0!==t.showButton&&(this.options.showButton=t.showButton),void 0!==t.enabled&&(e=t.enabled)}else"boolean"==typeof t?(this.options.filter=!0,e=t):"function"==typeof t&&(this.options.filter=t,e=!0);!1===ig(this.options)&&(e=!1),this.options.enabled=e}this._clean()}},{key:"setModuleOptions",value:function(t){this.moduleOptions=t,!0===this.options.enabled&&(this._clean(),void 0!==this.options.container&&(this.container=this.options.container),this._create())}},{key:"_create",value:function(){this._clean(),this.changedOptions=[];var t=ig(this.options),e=0,i=!1;for(var n in this.configureOptions)Object.prototype.hasOwnProperty.call(this.configureOptions,n)&&(this.allowCreation=!1,i=!1,"function"==typeof t?i=(i=t(n,[]))||this._handleObject(this.configureOptions[n],[n],!0):!0!==t&&-1===Qg(t).call(t,n)||(i=!0),!1!==i&&(this.allowCreation=!0,e>0&&this._makeItem([]),this._makeHeader(n),this._handleObject(this.configureOptions[n],[n])),e++);this._makeButton(),this._push()}},{key:"_push",value:function(){this.wrapper=document.createElement("div"),this.wrapper.className="vis-configuration-wrapper",this.container.appendChild(this.wrapper);for(var t=0;t1?i-1:0),r=1;r2&&void 0!==arguments[2]&&arguments[2],n=document.createElement("div");if(n.className="vis-configuration vis-config-label vis-config-s"+e.length,!0===i){for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(sk("i","b",t))}else n.innerText=t+":";return n}},{key:"_makeDropdown",value:function(t,e,i){var n=document.createElement("select");n.className="vis-configuration vis-config-select";var r=0;void 0!==e&&-1!==Qg(t).call(t,e)&&(r=Qg(t).call(t,e));for(var o=0;oo&&1!==o&&(a.max=Math.ceil(e*u),h=a.max,l="range increased"),a.value=e}else a.value=n;var c=document.createElement("input");c.className="vis-configuration vis-config-rangeinput",c.value=a.value;var d=this;a.onchange=function(){c.value=this.value,d._update(Number(this.value),i)},a.oninput=function(){c.value=this.value};var p=this._makeLabel(i[i.length-1],i),f=this._makeItem(i,p,a,c);""!==l&&this.popupHistory[f]!==h&&(this.popupHistory[f]=h,this._setupPopup(l,f))}},{key:"_makeButton",value:function(){var t=this;if(!0===this.options.showButton){var e=document.createElement("div");e.className="vis-configuration vis-config-button",e.innerText="generate options",e.onclick=function(){t._printOptions()},e.onmouseover=function(){e.className="vis-configuration vis-config-button hover"},e.onmouseout=function(){e.className="vis-configuration vis-config-button"},this.optionsContainer=document.createElement("div"),this.optionsContainer.className="vis-configuration vis-config-option-container",this.domElements.push(this.optionsContainer),this.domElements.push(e)}}},{key:"_setupPopup",value:function(t,e){var i=this;if(!0===this.initialized&&!0===this.allowCreation&&this.popupCounter1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=!1,r=ig(this.options),o=!1;for(var s in t)if(Object.prototype.hasOwnProperty.call(t,s)){n=!0;var a=t[s],l=Gw(e,s);if("function"==typeof r&&!1===(n=r(s,e))&&!tf(a)&&"string"!=typeof a&&"boolean"!=typeof a&&a instanceof Object&&(this.allowCreation=!1,n=this._handleObject(a,l,!0),this.allowCreation=!1===i),!1!==n){o=!0;var h=this._getValue(l);if(tf(a))this._handleArray(a,h,l);else if("string"==typeof a)this._makeTextInput(a,h,l);else if("boolean"==typeof a)this._makeCheckbox(a,h,l);else if(a instanceof Object){if(!this.hideOption(e,s,this.moduleOptions))if(void 0!==a.enabled){var u=Gw(l,"enabled"),c=this._getValue(u);if(!0===c){var d=this._makeLabel(s,l,!0);this._makeItem(l,d),o=this._handleObject(a,l)||o}else this._makeCheckbox(a,c,l)}else{var p=this._makeLabel(s,l,!0);this._makeItem(l,p),o=this._handleObject(a,l)||o}}else console.error("dont know how to handle",a,s,l)}}return o}},{key:"_handleArray",value:function(t,e,i){"string"==typeof t[0]&&"color"===t[0]?(this._makeColorField(t,e,i),t[1]!==e&&this.changedOptions.push({path:i,value:e})):"string"==typeof t[0]?(this._makeDropdown(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:e})):"number"==typeof t[0]&&(this._makeRange(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:Number(e)}))}},{key:"_update",value:function(t,e){var i=this._constructOptions(t,e);this.parent.body&&this.parent.body.emitter&&this.parent.body.emitter.emit&&this.parent.body.emitter.emit("configChange",i),this.initialized=!0,this.parent.setOptions(i)}},{key:"_constructOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=i;t="false"!==(t="true"===t||t)&&t;for(var r=0;rr-this.padding&&(a=!0),o=a?this.x-i:this.x,s=l?this.y-e:this.y}else(s=this.y-e)+e+this.padding>n&&(s=n-e-this.padding),sr&&(o=r-i-this.padding),os.distance?" in "+t.printLocation(o.path,e,"")+"Perhaps it was misplaced? Matching option found at: "+t.printLocation(s.path,s.closestMatch,""):o.distance<=8?'. Did you mean "'+o.closestMatch+'"?'+t.printLocation(o.path,e):". Did you mean one of these: "+t.print(gf(i))+t.printLocation(n,e),console.error('%cUnknown option detected: "'+e+'"'+r,ck),uk=!0}},{key:"findInOptions",value:function(e,i,n){var r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],o=1e9,s="",a=[],l=e.toLowerCase(),h=void 0;for(var u in i){var c=void 0;if(void 0!==i[u].__type__&&!0===r){var d=t.findInOptions(e,i[u],Gw(n,u));o>d.distance&&(s=d.closestMatch,a=d.path,o=d.distance,h=d.indexMatch)}else{var p;-1!==Qg(p=u.toLowerCase()).call(p,l)&&(h=u),o>(c=t.levenshteinDistance(e,u))&&(s=u,a=Ww(n),o=c)}}return{closestMatch:s,path:a,distance:o,indexMatch:h}}},{key:"printLocation",value:function(t,e){for(var i="\n\n"+(arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Problem value found at: \n")+"options = {\n",n=0;n>>0,t=(r*=t)>>>0,t+=4294967296*(r-=t)}return 2.3283064365386963e-10*(t>>>0)}}(),e=t(" "),i=t(" "),n=t(" "),r=0;r0)return"before"==n?Math.max(0,l-1):l;if(r(s,e)<0&&r(a,e)>0)return"before"==n?l:Math.min(t.length-1,l+1);r(s,e)<0?u=l+1:c=l-1,h++}return-1},bridgeObject:nk,copyAndExtendArray:Gw,copyArray:Ww,deepExtend:zw,deepObjectAssign:Sw,easingFunctions:{linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return t*(2-t)},easeInOutQuad:function(t){return t<.5?2*t*t:(4-2*t)*t-1},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return--t*t*t+1},easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return 1- --t*t*t*t},easeInOutQuart:function(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return 1+--t*t*t*t*t},easeInOutQuint:function(t){return t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t}},equalArray:function(t,e){if(t.length!==e.length)return!1;for(var i=0,n=t.length;i2&&void 0!==arguments[2]&&arguments[2];for(var r in e)if(void 0!==i[r])if(null===i[r]||"object"!==Nd(i[r]))Yw(e,i,r,n);else{var o=e[r],s=i[r];jw(o)&&jw(s)&&t(o,s,n)}},forEach:function(t,e){if(tf(t))for(var i=t.length,n=0;n0&&void 0!==arguments[0]?arguments[0]:window.event,e=null;return t&&(t.target?e=t.target:t.srcElement&&(e=t.srcElement)),e instanceof Element&&(null==e.nodeType||3!=e.nodeType||(e=e.parentNode)instanceof Element)?e:null},getType:Bw,hasParent:function(t,e){for(var i=t;i;){if(i===e)return!0;if(!i.parentNode)return!1;i=i.parentNode}return!1},hexToHSV:Qw,hexToRGB:Xw,insertSort:function(t,e){for(var i=0;i0&&e(n,t[r-1])<0;r--)t[r]=t[r-1];t[r]=n}return t},isDate:function(t){if(t instanceof Date)return!0;if(Fw(t)){if(Pw.exec(t))return!0;if(!isNaN(Date.parse(t)))return!0}return!1},isNumber:Rw,isObject:jw,isString:Fw,isValidHex:tk,isValidRGB:ek,isValidRGBA:ik,mergeOptions:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},r=function(t){return null!=t},o=function(t){return null!==t&&"object"===Nd(t)};if(!o(t))throw new Error("Parameter mergeTarget must be an object");if(!o(e))throw new Error("Parameter options must be an object");if(!r(i))throw new Error("Parameter option must have a value");if(!o(n))throw new Error("Parameter globalOptions must be an object");var s=e[i],a=o(n)&&!function(t){for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e))return!1;return!0}(n)?n[i]:void 0,l=a?a.enabled:void 0;if(void 0!==s){if("boolean"==typeof s)return o(t[i])||(t[i]={}),void(t[i].enabled=s);if(null===s&&!o(t[i])){if(!r(a))return;t[i]=gy(a)}if(o(s)){var h=!0;void 0!==s.enabled?h=s.enabled:void 0!==l&&(h=a.enabled),function(t,e,i){o(t[i])||(t[i]={});var n=e[i],r=t[i];for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(r[s]=n[s])}(t,e,i),t[i].enabled=h}}},option:Uw,overrideOpacity:function(t,e){if(Yv(t).call(t,"rgba"))return t;if(Yv(t).call(t,"rgb")){var i=t.substr(Qg(t).call(t,"(")+1).replace(")","").split(",");return"rgba("+i[0]+","+i[1]+","+i[2]+","+e+")"}var n=Xw(t);return null==n?t:"rgba("+n.r+","+n.g+","+n.b+","+e+")"},parseColor:function(t,e){if(Fw(t)){var i=t;if(ek(i)){var n,r=cf(n=i.substr(4).substr(0,i.length-5).split(",")).call(n,(function(t){return Yg(t)}));i=qw(r[0],r[1],r[2])}if(!0===tk(i)){var o=Qw(i),s={h:o.h,s:.8*o.s,v:Math.min(1,1.02*o.v)},a={h:o.h,s:Math.min(1,1.25*o.s),v:.8*o.v},l=Jw(a.h,a.s,a.v),h=Jw(s.h,s.s,s.v);return{background:i,border:l,highlight:{background:h,border:l},hover:{background:h,border:l}}}return{background:i,border:i,highlight:{background:i,border:i},hover:{background:i,border:i}}}return e?{background:t.background||e.background,border:t.border||e.border,highlight:Fw(t.highlight)?{border:t.highlight,background:t.highlight}:{background:t.highlight&&t.highlight.background||e.highlight.background,border:t.highlight&&t.highlight.border||e.highlight.border},hover:Fw(t.hover)?{border:t.hover,background:t.hover}:{border:t.hover&&t.hover.border||e.hover.border,background:t.hover&&t.hover.background||e.hover.background}}:{background:t.background||void 0,border:t.border||void 0,highlight:Fw(t.highlight)?{border:t.highlight,background:t.highlight}:{background:t.highlight&&t.highlight.background||void 0,border:t.highlight&&t.highlight.border||void 0},hover:Fw(t.hover)?{border:t.hover,background:t.hover}:{border:t.hover&&t.hover.border||void 0,background:t.hover&&t.hover.background||void 0}}},preventDefault:function(t){t||(t=window.event),t&&(t.preventDefault?t.preventDefault():t.returnValue=!1)},pureDeepObjectAssign:Dw,recursiveDOMDelete:function t(e){if(e)for(;!0===e.hasChildNodes();){var i=e.firstChild;i&&(t(i),e.removeChild(i))}},removeClassName:function(t,e){var i=t.className.split(" "),n=e.split(" ");i=ig(i).call(i,(function(t){return!Yv(n).call(n,t)})),t.className=i.join(" ")},removeCssText:function(t,e){var i=Zw.split(t.style.cssText),n=Zw.split(e);for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&delete i[r];t.style.cssText=Zw.join(i)},removeEventListener:function(t,e,i,n){var r;t.removeEventListener?(void 0===n&&(n=!1),"mousewheel"===e&&Yv(r=navigator.userAgent).call(r,"Firefox")&&(e="DOMMouseScroll"),t.removeEventListener(e,i,n)):t.detachEvent("on"+e,i)},selectiveBridgeObject:function(t,e){if(null!==e&&"object"===Nd(e)){for(var i=gy(e),n=0;n3&&void 0!==arguments[3]&&arguments[3];if(tf(i))throw new TypeError("Arrays are not supported by deepExtend");for(var r=0;r2?i-2:0),r=2;r3&&void 0!==arguments[3]&&arguments[3];if(tf(i))throw new TypeError("Arrays are not supported by deepExtend");for(var r in i)if(Object.prototype.hasOwnProperty.call(i,r)&&!Yv(t).call(t,r))if(i[r]&&i[r].constructor===Object)void 0===e[r]&&(e[r]={}),e[r].constructor===Object?zw(e[r],i[r]):Yw(e,i,r,n);else if(tf(i[r])){e[r]=[];for(var o=0;o0?(n=e[t].redundant[0],e[t].redundant.shift()):(n=document.createElementNS("http://www.w3.org/2000/svg",t),i.appendChild(n)):(n=document.createElementNS("http://www.w3.org/2000/svg",t),e[t]={used:[],redundant:[]},i.appendChild(n)),e[t].used.push(n),n}function Sk(t,e,i,n){var r;return e.hasOwnProperty(t)?e[t].redundant.length>0?(r=e[t].redundant[0],e[t].redundant.shift()):(r=document.createElement(t),void 0!==n?i.insertBefore(r,n):i.appendChild(r)):(r=document.createElement(t),e[t]={used:[],redundant:[]},void 0!==n?i.insertBefore(r,n):i.appendChild(r)),e[t].used.push(r),r}function Ck(t,e,i,n,r,o){var s;if("circle"==i.style?((s=Dk("circle",n,r)).setAttributeNS(null,"cx",t),s.setAttributeNS(null,"cy",e),s.setAttributeNS(null,"r",.5*i.size)):((s=Dk("rect",n,r)).setAttributeNS(null,"x",t-.5*i.size),s.setAttributeNS(null,"y",e-.5*i.size),s.setAttributeNS(null,"width",i.size),s.setAttributeNS(null,"height",i.size)),void 0!==i.styles&&s.setAttributeNS(null,"style",i.styles),s.setAttributeNS(null,"class",i.className+" vis-point"),o){var a=Dk("text",n,r);o.xOffset&&(t+=o.xOffset),o.yOffset&&(e+=o.yOffset),o.content&&(a.textContent=o.content),o.className&&a.setAttributeNS(null,"class",o.className+" vis-label"),a.setAttributeNS(null,"x",t),a.setAttributeNS(null,"y",e)}return s}function Tk(t,e,i,n,r,o,s,a){if(0!=n){n<0&&(e-=n*=-1);var l=Dk("rect",o,s);l.setAttributeNS(null,"x",t-.5*i),l.setAttributeNS(null,"y",e),l.setAttributeNS(null,"width",i),l.setAttributeNS(null,"height",n),l.setAttributeNS(null,"class",r),a&&l.setAttributeNS(null,"style",a)}}function Mk(){try{return navigator?navigator.languages&&navigator.languages.length?navigator.languages:navigator.userLanguage||navigator.language||navigator.browserLanguage||"en":"en"}catch(t){return"en"}}var Ok=Object.freeze({__proto__:null,cleanupElements:kk,drawBar:Tk,drawPoint:Ck,getDOMElement:Sk,getNavigatorLanguage:Mk,getSVGElement:Dk,prepareElements:wk,resetElements:xk});function Ek(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}var Pk={},Ik={get exports(){return Pk},set exports(t){Pk=t}},Ak={},Lk=vy;!function(t){t.exports=Lk}({get exports(){return Ak},set exports(t){Ak=t}}),function(t){t.exports=Ak}(Ik);var Nk=n(Pk),Rk={},Fk={get exports(){return Rk},set exports(t){Rk=t}},jk={},Yk={get exports(){return jk},set exports(t){jk=t}};In({target:"Object",stat:!0},{setPrototypeOf:Co});var Hk=fe.Object.setPrototypeOf;!function(t){t.exports=Hk}(Yk),function(t){t.exports=jk}(Fk);var zk=n(Rk),Bk={},Gk={get exports(){return Bk},set exports(t){Bk=t}},Wk={},Vk=Vf;!function(t){t.exports=Vk}({get exports(){return Wk},set exports(t){Wk=t}}),function(t){t.exports=Wk}(Gk);var Uk=n(Bk);function Xk(t,e){var i;return Xk=zk?Uk(i=zk).call(i):function(t,e){return t.__proto__=e,t},Xk(t,e)}function qk(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Nk(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Ec(t,"prototype",{writable:!1}),e&&Xk(t,e)}function $k(t,e){if(e&&("object"===Nd(e)||"function"==typeof e))return e;if(void 0!==e)throw new TypeError("Derived constructors may only return object or undefined");return Ek(t)}var Zk={},Kk={get exports(){return Zk},set exports(t){Zk=t}},Jk={},Qk=Vv;!function(t){t.exports=Qk}({get exports(){return Jk},set exports(t){Jk=t}}),function(t){t.exports=Jk}(Kk);var tx=n(Zk);function ex(t){var e;return ex=zk?Uk(e=tx).call(e):function(t){return t.__proto__||tx(t)},ex(t)}var ix={},nx={get exports(){return ix},set exports(t){ix=t}},rx={};!function(t){var e=Pc,i=Md;function n(r){return t.exports=n="function"==typeof e&&"symbol"==typeof i?function(t){return typeof t}:function(t){return t&&"function"==typeof e&&t.constructor===e&&t!==e.prototype?"symbol":typeof t},t.exports.__esModule=!0,t.exports.default=t.exports,n(r)}t.exports=n,t.exports.__esModule=!0,t.exports.default=t.exports}({get exports(){return rx},set exports(t){rx=t}});var ox={},sx={get exports(){return ox},set exports(t){ox=t}},ax={},lx=sm;!function(t){t.exports=lx}({get exports(){return ax},set exports(t){ax=t}}),function(t){t.exports=ax}(sx);var hx={},ux={get exports(){return hx},set exports(t){hx=t}},cx={},dx={get exports(){return cx},set exports(t){cx=t}},px=W,fx=Zu,mx=Yi,vx=Qt,gx=Kt,yx=di,bx=Error,_x=y("".replace),wx=String(bx("zxcasd").stack),kx=/\n\s*at [^:]*:[^\n]*/,xx=kx.test(wx),Dx=hi,Sx=!d((function(){var t=Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",Dx(1,7)),7!==t.stack)})),Cx=di,Tx=function(t,e){if(xx&&"string"==typeof t&&!bx.prepareStackTrace)for(;e--;)t=_x(t,kx,"");return t},Mx=Sx,Ox=Error.captureStackTrace,Ex=_n,Px=pe,Ix=ue,Ax=Te,Lx=ss,Nx=Xn,Rx=_e,Fx=zs,jx=Ls,Yx=ts,Hx=TypeError,zx=function(t,e){this.stopped=t,this.result=e},Bx=zx.prototype,Gx=function(t,e,i){var n,r,o,s,a,l,h,u=i&&i.that,c=!(!i||!i.AS_ENTRIES),d=!(!i||!i.IS_RECORD),p=!(!i||!i.IS_ITERATOR),f=!(!i||!i.INTERRUPTED),m=Ex(e,u),v=function(t){return n&&Yx(n,"normal",t),new zx(!0,t)},g=function(t){return c?(Ix(t),f?m(t[0],t[1],v):m(t[0],t[1])):f?m(t,v):m(t)};if(d)n=t.iterator;else if(p)n=t;else{if(!(r=jx(t)))throw Hx(Ax(t)+" is not iterable");if(Lx(r)){for(o=0,s=Nx(t);s>o;o++)if((a=g(t[o]))&&Rx(Bx,a))return a;return new zx(!1)}n=Fx(t,r)}for(l=d?t.next:n.next;!(h=Px(l,n)).done;){try{a=g(h.value)}catch(t){Yx(n,"throw",t)}if("object"==typeof a&&a&&Rx(Bx,a))return a}return new zx(!1)},Wx=Rt,Vx=In,Ux=_e,Xx=Br,qx=Co,$x=function(t,e,i){for(var n=fx(e),r=vx.f,o=mx.f,s=0;s2&&Qx(i,arguments[2]);var r=[];return eD(t,oD,{that:r}),Kx(i,"errors",r),i};qx?qx(sD,rD):$x(sD,rD,{name:!0});var aD=sD.prototype=Zx(rD.prototype,{constructor:Jx(1,sD),message:Jx(1,""),name:Jx(1,"AggregateError")});Vx({global:!0,constructor:!0,arity:2},{AggregateError:sD});var lD,hD,uD,cD,dD="undefined"!=typeof process&&"process"==Ct(process),pD=be,fD=Za,mD=Jt,vD=vt("species"),gD=function(t){var e=pD(t);mD&&e&&!e[vD]&&fD(e,vD,{configurable:!0,get:function(){return this}})},yD=_e,bD=TypeError,_D=function(t,e){if(yD(e,t))return t;throw bD("Incorrect invocation")},wD=Ds,kD=Te,xD=TypeError,DD=function(t){if(wD(t))return t;throw xD(kD(t)+" is not a constructor")},SD=ue,CD=DD,TD=N,MD=vt("species"),OD=function(t,e){var i,n=SD(t).constructor;return void 0===n||TD(i=SD(n)[MD])?e:CD(i)},ED=/(?:ipad|iphone|ipod).*applewebkit/i.test(Z),PD=D,ID=Ni,AD=_n,LD=kt,ND=W,RD=d,FD=vr,jD=$h,YD=ne,HD=Oy,zD=ED,BD=dD,GD=PD.setImmediate,WD=PD.clearImmediate,VD=PD.process,UD=PD.Dispatch,XD=PD.Function,qD=PD.MessageChannel,$D=PD.String,ZD=0,KD={},JD="onreadystatechange";RD((function(){lD=PD.location}));var QD=function(t){if(ND(KD,t)){var e=KD[t];delete KD[t],e()}},tS=function(t){return function(){QD(t)}},eS=function(t){QD(t.data)},iS=function(t){PD.postMessage($D(t),lD.protocol+"//"+lD.host)};GD&&WD||(GD=function(t){HD(arguments.length,1);var e=LD(t)?t:XD(t),i=jD(arguments,1);return KD[++ZD]=function(){ID(e,void 0,i)},hD(ZD),ZD},WD=function(t){delete KD[t]},BD?hD=function(t){VD.nextTick(tS(t))}:UD&&UD.now?hD=function(t){UD.now(tS(t))}:qD&&!zD?(cD=(uD=new qD).port2,uD.port1.onmessage=eS,hD=AD(cD.postMessage,cD)):PD.addEventListener&&LD(PD.postMessage)&&!PD.importScripts&&lD&&"file:"!==lD.protocol&&!RD(iS)?(hD=iS,PD.addEventListener("message",eS,!1)):hD=JD in YD("script")?function(t){FD.appendChild(YD("script"))[JD]=function(){FD.removeChild(this),QD(t)}}:function(t){setTimeout(tS(t),0)});var nS={set:GD,clear:WD},rS=function(){this.head=null,this.tail=null};rS.prototype={add:function(t){var e={item:t,next:null},i=this.tail;i?i.next=e:this.head=e,this.tail=e},get:function(){var t=this.head;if(t)return null===(this.head=t.next)&&(this.tail=null),t.item}};var oS,sS,aS,lS,hS,uS=rS,cS=/ipad|iphone|ipod/i.test(Z)&&"undefined"!=typeof Pebble,dS=/web0s(?!.*chrome)/i.test(Z),pS=D,fS=_n,mS=Yi.f,vS=nS.set,gS=uS,yS=ED,bS=cS,_S=dS,wS=dD,kS=pS.MutationObserver||pS.WebKitMutationObserver,xS=pS.document,DS=pS.process,SS=pS.Promise,CS=mS(pS,"queueMicrotask"),TS=CS&&CS.value;if(!TS){var MS=new gS,OS=function(){var t,e;for(wS&&(t=DS.domain)&&t.exit();e=MS.get();)try{e()}catch(t){throw MS.head&&oS(),t}t&&t.enter()};yS||wS||_S||!kS||!xS?!bS&&SS&&SS.resolve?((lS=SS.resolve(void 0)).constructor=SS,hS=fS(lS.then,lS),oS=function(){hS(OS)}):wS?oS=function(){DS.nextTick(OS)}:(vS=fS(vS,pS),oS=function(){vS(OS)}):(sS=!0,aS=xS.createTextNode(""),new kS(OS).observe(aS,{characterData:!0}),oS=function(){aS.data=sS=!sS}),TS=function(t){MS.head||oS(),MS.add(t)}}var ES=TS,PS=function(t){try{return{error:!1,value:t()}}catch(t){return{error:!0,value:t}}},IS=D.Promise,AS="object"==typeof Deno&&Deno&&"object"==typeof Deno.version,LS=!AS&&!dD&&"object"==typeof window&&"object"==typeof document,NS=D,RS=IS,FS=kt,jS=vn,YS=us,HS=vt,zS=LS,BS=AS,GS=nt,WS=RS&&RS.prototype,VS=HS("species"),US=!1,XS=FS(NS.PromiseRejectionEvent),qS=jS("Promise",(function(){var t=YS(RS),e=t!==String(RS);if(!e&&66===GS)return!0;if(!WS.catch||!WS.finally)return!0;if(!GS||GS<51||!/native code/.test(t)){var i=new RS((function(t){t(1)})),n=function(t){t((function(){}),(function(){}))};if((i.constructor={})[VS]=n,!(US=i.then((function(){}))instanceof n))return!0}return!e&&(zS||BS)&&!XS})),$S={CONSTRUCTOR:qS,REJECTION_EVENT:XS,SUBCLASSING:US},ZS={},KS=Pe,JS=TypeError,QS=function(t){var e,i;this.promise=new t((function(t,n){if(void 0!==e||void 0!==i)throw JS("Bad Promise constructor");e=t,i=n})),this.resolve=KS(e),this.reject=KS(i)};ZS.f=function(t){return new QS(t)};var tC,eC,iC=In,nC=dD,rC=D,oC=pe,sC=Wr,aC=ho,lC=gD,hC=Pe,uC=kt,cC=Kt,dC=_D,pC=OD,fC=nS.set,mC=ES,vC=function(t,e){try{1==arguments.length?console.error(t):console.error(t,e)}catch(t){}},gC=PS,yC=uS,bC=Ei,_C=IS,wC=ZS,kC="Promise",xC=$S.CONSTRUCTOR,DC=$S.REJECTION_EVENT,SC=bC.getterFor(kC),CC=bC.set,TC=_C&&_C.prototype,MC=_C,OC=TC,EC=rC.TypeError,PC=rC.document,IC=rC.process,AC=wC.f,LC=AC,NC=!!(PC&&PC.createEvent&&rC.dispatchEvent),RC="unhandledrejection",FC=function(t){var e;return!(!cC(t)||!uC(e=t.then))&&e},jC=function(t,e){var i,n,r,o=e.value,s=1==e.state,a=s?t.ok:t.fail,l=t.resolve,h=t.reject,u=t.domain;try{a?(s||(2===e.rejection&&GC(e),e.rejection=1),!0===a?i=o:(u&&u.enter(),i=a(o),u&&(u.exit(),r=!0)),i===t.promise?h(EC("Promise-chain cycle")):(n=FC(i))?oC(n,i,l,h):l(i)):h(o)}catch(t){u&&!r&&u.exit(),h(t)}},YC=function(t,e){t.notified||(t.notified=!0,mC((function(){for(var i,n=t.reactions;i=n.get();)jC(i,t);t.notified=!1,e&&!t.rejection&&zC(t)})))},HC=function(t,e,i){var n,r;NC?((n=PC.createEvent("Event")).promise=e,n.reason=i,n.initEvent(t,!1,!0),rC.dispatchEvent(n)):n={promise:e,reason:i},!DC&&(r=rC["on"+t])?r(n):t===RC&&vC("Unhandled promise rejection",i)},zC=function(t){oC(fC,rC,(function(){var e,i=t.facade,n=t.value;if(BC(t)&&(e=gC((function(){nC?IC.emit("unhandledRejection",n,i):HC(RC,i,n)})),t.rejection=nC||BC(t)?2:1,e.error))throw e.value}))},BC=function(t){return 1!==t.rejection&&!t.parent},GC=function(t){oC(fC,rC,(function(){var e=t.facade;nC?IC.emit("rejectionHandled",e):HC("rejectionhandled",e,t.value)}))},WC=function(t,e,i){return function(n){t(e,n,i)}},VC=function(t,e,i){t.done||(t.done=!0,i&&(t=i),t.value=e,t.state=2,YC(t,!0))},UC=function(t,e,i){if(!t.done){t.done=!0,i&&(t=i);try{if(t.facade===e)throw EC("Promise can't be resolved itself");var n=FC(e);n?mC((function(){var i={done:!1};try{oC(n,e,WC(UC,i,t),WC(VC,i,t))}catch(e){VC(i,e,t)}})):(t.value=e,t.state=1,YC(t,!1))}catch(e){VC({done:!1},e,t)}}};xC&&(OC=(MC=function(t){dC(this,OC),hC(t),oC(tC,this);var e=SC(this);try{t(WC(UC,e),WC(VC,e))}catch(t){VC(e,t)}}).prototype,(tC=function(t){CC(this,{type:kC,done:!1,notified:!1,parent:!1,reactions:new yC,rejection:!1,state:0,value:void 0})}).prototype=sC(OC,"then",(function(t,e){var i=SC(this),n=AC(pC(this,MC));return i.parent=!0,n.ok=!uC(t)||t,n.fail=uC(e)&&e,n.domain=nC?IC.domain:void 0,0==i.state?i.reactions.add(n):mC((function(){jC(n,i)})),n.promise})),eC=function(){var t=new tC,e=SC(t);this.promise=t,this.resolve=WC(UC,e),this.reject=WC(VC,e)},wC.f=AC=function(t){return t===MC||undefined===t?new eC(t):LC(t)}),iC({global:!0,constructor:!0,wrap:!0,forced:xC},{Promise:MC}),aC(MC,kC,!1,!0),lC(kC);var XC=IS,qC=$S.CONSTRUCTOR||!na((function(t){XC.all(t).then(void 0,(function(){}))})),$C=pe,ZC=Pe,KC=ZS,JC=PS,QC=Gx;In({target:"Promise",stat:!0,forced:qC},{all:function(t){var e=this,i=KC.f(e),n=i.resolve,r=i.reject,o=JC((function(){var i=ZC(e.resolve),o=[],s=0,a=1;QC(t,(function(t){var l=s++,h=!1;a++,$C(i,e,t).then((function(t){h||(h=!0,o[l]=t,--a||n(o))}),r)})),--a||n(o)}));return o.error&&r(o.value),i.promise}});var tT=In,eT=$S.CONSTRUCTOR;IS&&IS.prototype,tT({target:"Promise",proto:!0,forced:eT,real:!0},{catch:function(t){return this.then(void 0,t)}});var iT=pe,nT=Pe,rT=ZS,oT=PS,sT=Gx;In({target:"Promise",stat:!0,forced:qC},{race:function(t){var e=this,i=rT.f(e),n=i.reject,r=oT((function(){var r=nT(e.resolve);sT(t,(function(t){iT(r,e,t).then(i.resolve,n)}))}));return r.error&&n(r.value),i.promise}});var aT=pe,lT=ZS;In({target:"Promise",stat:!0,forced:$S.CONSTRUCTOR},{reject:function(t){var e=lT.f(this);return aT(e.reject,void 0,t),e.promise}});var hT=ue,uT=Kt,cT=ZS,dT=function(t,e){if(hT(t),uT(e)&&e.constructor===t)return e;var i=cT.f(t);return(0,i.resolve)(e),i.promise},pT=In,fT=IS,mT=$S.CONSTRUCTOR,vT=dT,gT=be("Promise"),yT=!mT;pT({target:"Promise",stat:!0,forced:true},{resolve:function(t){return vT(yT&&this===gT?fT:this,t)}});var bT=pe,_T=Pe,wT=ZS,kT=PS,xT=Gx;In({target:"Promise",stat:!0,forced:qC},{allSettled:function(t){var e=this,i=wT.f(e),n=i.resolve,r=i.reject,o=kT((function(){var i=_T(e.resolve),r=[],o=0,s=1;xT(t,(function(t){var a=o++,l=!1;s++,bT(i,e,t).then((function(t){l||(l=!0,r[a]={status:"fulfilled",value:t},--s||n(r))}),(function(t){l||(l=!0,r[a]={status:"rejected",reason:t},--s||n(r))}))})),--s||n(r)}));return o.error&&r(o.value),i.promise}});var DT=pe,ST=Pe,CT=be,TT=ZS,MT=PS,OT=Gx,ET="No one promise resolved";In({target:"Promise",stat:!0,forced:qC},{any:function(t){var e=this,i=CT("AggregateError"),n=TT.f(e),r=n.resolve,o=n.reject,s=MT((function(){var n=ST(e.resolve),s=[],a=0,l=1,h=!1;OT(t,(function(t){var u=a++,c=!1;l++,DT(n,e,t).then((function(t){c||h||(h=!0,r(t))}),(function(t){c||h||(c=!0,s[u]=t,--l||o(new i(s,ET)))}))})),--l||o(new i(s,ET))}));return s.error&&o(s.value),n.promise}});var PT=In,IT=IS,AT=d,LT=be,NT=kt,RT=OD,FT=dT,jT=IT&&IT.prototype;PT({target:"Promise",proto:!0,real:!0,forced:!!IT&&AT((function(){jT.finally.call({then:function(){}},(function(){}))}))},{finally:function(t){var e=RT(this,LT("Promise")),i=NT(t);return this.then(i?function(i){return FT(e,t()).then((function(){return i}))}:t,i?function(i){return FT(e,t()).then((function(){throw i}))}:t)}});var YT=fe.Promise,HT=ZS,zT=PS;In({target:"Promise",stat:!0,forced:!0},{try:function(t){var e=HT.f(this),i=zT(t);return(i.error?e.reject:e.resolve)(i.value),e.promise}});var BT=YT;!function(t){t.exports=BT}(dx),function(t){t.exports=cx}(ux);var GT={},WT={get exports(){return GT},set exports(t){GT=t}},VT={},UT=bm;!function(t){t.exports=UT}({get exports(){return VT},set exports(t){VT=t}}),function(t){t.exports=VT}(WT),function(t){var e=rx.default,i=Cc,n=Pc,r=Pk,o=Zk,s=ox,a=Rk,l=hx,h=GT,u=Qd;function c(){t.exports=c=function(){return d},t.exports.__esModule=!0,t.exports.default=t.exports;var d={},p=Object.prototype,f=p.hasOwnProperty,m=i||function(t,e,i){t[e]=i.value},v="function"==typeof n?n:{},g=v.iterator||"@@iterator",y=v.asyncIterator||"@@asyncIterator",b=v.toStringTag||"@@toStringTag";function _(t,e,n){return i(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{_({},"")}catch(t){_=function(t,e,i){return t[e]=i}}function w(t,e,i,n){var o=e&&e.prototype instanceof D?e:D,s=r(o.prototype),a=new R(n||[]);return m(s,"_invoke",{value:I(t,i,a)}),s}function k(t,e,i){try{return{type:"normal",arg:t.call(e,i)}}catch(t){return{type:"throw",arg:t}}}d.wrap=w;var x={};function D(){}function S(){}function C(){}var T={};_(T,g,(function(){return this}));var M=o&&o(o(F([])));M&&M!==p&&f.call(M,g)&&(T=M);var O=C.prototype=D.prototype=r(T);function E(t){var e;s(e=["next","throw","return"]).call(e,(function(e){_(t,e,(function(t){return this._invoke(e,t)}))}))}function P(t,i){function n(r,o,s,a){var l=k(t[r],t,o);if("throw"!==l.type){var h=l.arg,u=h.value;return u&&"object"==e(u)&&f.call(u,"__await")?i.resolve(u.__await).then((function(t){n("next",t,s,a)}),(function(t){n("throw",t,s,a)})):i.resolve(u).then((function(t){h.value=t,s(h)}),(function(t){return n("throw",t,s,a)}))}a(l.arg)}var r;m(this,"_invoke",{value:function(t,e){function o(){return new i((function(i,r){n(t,e,i,r)}))}return r=r?r.then(o,o):o()}})}function I(t,e,i){var n="suspendedStart";return function(r,o){if("executing"===n)throw new Error("Generator is already running");if("completed"===n){if("throw"===r)throw o;return j()}for(i.method=r,i.arg=o;;){var s=i.delegate;if(s){var a=A(s,i);if(a){if(a===x)continue;return a}}if("next"===i.method)i.sent=i._sent=i.arg;else if("throw"===i.method){if("suspendedStart"===n)throw n="completed",i.arg;i.dispatchException(i.arg)}else"return"===i.method&&i.abrupt("return",i.arg);n="executing";var l=k(t,e,i);if("normal"===l.type){if(n=i.done?"completed":"suspendedYield",l.arg===x)continue;return{value:l.arg,done:i.done}}"throw"===l.type&&(n="completed",i.method="throw",i.arg=l.arg)}}}function A(t,e){var i=e.method,n=t.iterator[i];if(void 0===n)return e.delegate=null,"throw"===i&&t.iterator.return&&(e.method="return",e.arg=void 0,A(t,e),"throw"===e.method)||"return"!==i&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+i+"' method")),x;var r=k(n,t.iterator,e.arg);if("throw"===r.type)return e.method="throw",e.arg=r.arg,e.delegate=null,x;var o=r.arg;return o?o.done?(e[t.resultName]=o.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=void 0),e.delegate=null,x):o:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,x)}function L(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function N(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function R(t){this.tryEntries=[{tryLoc:"root"}],s(t).call(t,L,this),this.reset(!0)}function F(t){if(t){var e=t[g];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var i=-1,n=function e(){for(;++i=0;--n){var r=this.tryEntries[n],o=r.completion;if("root"===r.tryLoc)return i("end");if(r.tryLoc<=this.prev){var s=f.call(r,"catchLoc"),a=f.call(r,"finallyLoc");if(s&&a){if(this.prev=0;--i){var n=this.tryEntries[i];if(n.tryLoc<=this.prev&&f.call(n,"finallyLoc")&&this.prev=0;--e){var i=this.tryEntries[e];if(i.finallyLoc===t)return this.complete(i.completion,i.afterLoc),N(i),x}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var i=this.tryEntries[e];if(i.tryLoc===t){var n=i.completion;if("throw"===n.type){var r=n.arg;N(i)}return r}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,i){return this.delegate={iterator:F(t),resultName:e,nextLoc:i},"next"===this.method&&(this.arg=void 0),x}},d}t.exports=c,t.exports.__esModule=!0,t.exports.default=t.exports}(nx);var XT=ix(),qT=XT;try{regeneratorRuntime=XT}catch(t){"object"==typeof globalThis?globalThis.regeneratorRuntime=XT:Function("r","regeneratorRuntime = r")(XT)}var $T={},ZT={get exports(){return $T},set exports(t){$T=t}},KT=Pe,JT=z,QT=qi,tM=Xn,eM=TypeError,iM=function(t){return function(e,i,n,r){KT(i);var o=JT(e),s=QT(o),a=tM(o),l=t?a-1:0,h=t?-1:1;if(n<2)for(;;){if(l in s){r=s[l],l+=h;break}if(l+=h,t?l<0:a<=l)throw eM("Reduce of empty array with no initial value")}for(;t?l>=0:a>l;l+=h)l in s&&(r=i(r,s[l],l,o));return r}},nM={left:iM(!1),right:iM(!0)}.left;In({target:"Array",proto:!0,forced:!dD&&nt>79&&nt<83||!Zf("reduce")},{reduce:function(t){var e=arguments.length;return nM(this,t,e,e>1?arguments[1]:void 0)}});var rM=yp("Array").reduce,oM=_e,sM=rM,aM=Array.prototype,lM=function(t){var e=t.reduce;return t===aM||oM(aM,t)&&e===aM.reduce?sM:e},hM=lM;!function(t){t.exports=hM}(ZT);var uM=n($T),cM={},dM={get exports(){return cM},set exports(t){cM=t}},pM=ul,fM=Xn,mM=Rc,vM=_n,gM=function(t,e,i,n,r,o,s,a){for(var l,h,u=r,c=0,d=!!s&&vM(s,a);c0&&pM(l)?(h=fM(l),u=gM(t,e,l,h,u,o-1)-1):(mM(u+1),t[u]=l),u++),c++;return u},yM=gM,bM=Pe,_M=z,wM=Xn,kM=gl;In({target:"Array",proto:!0},{flatMap:function(t){var e,i=_M(this),n=wM(i);return bM(t),(e=kM(i,0)).length=yM(e,i,i,n,0,1,t,arguments.length>1?arguments[1]:void 0),e}});var xM=yp("Array").flatMap,DM=_e,SM=xM,CM=Array.prototype,TM=function(t){var e=t.flatMap;return t===CM||DM(CM,t)&&e===CM.flatMap?SM:e},MM=TM;!function(t){t.exports=MM}(dM);var OM=n(cM),EM={},PM={get exports(){return EM},set exports(t){EM=t}},IM={},AM={get exports(){return IM},set exports(t){IM=t}},LM=d((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),NM=d,RM=Kt,FM=Ct,jM=LM,YM=Object.isExtensible,HM=NM((function(){YM(1)}))||jM?function(t){return!!RM(t)&&((!jM||"ArrayBuffer"!=FM(t))&&(!YM||YM(t)))}:YM,zM=!d((function(){return Object.isExtensible(Object.preventExtensions({}))})),BM=In,GM=y,WM=vi,VM=Kt,UM=W,XM=Qt.f,qM=Aa,$M=Ra,ZM=HM,KM=zM,JM=!1,QM=$("meta"),tO=0,eO=function(t){XM(t,QM,{value:{objectID:"O"+tO++,weakData:{}}})},iO=AM.exports={enable:function(){iO.enable=function(){},JM=!0;var t=qM.f,e=GM([].splice),i={};i[QM]=1,t(i).length&&(qM.f=function(i){for(var n=t(i),r=0,o=n.length;r1?arguments[1]:void 0);e=e?e.next:i.first;)for(n(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!l(this,t)}}),kO(o,i?{get:function(t){var e=l(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),EO&&wO(o,"size",{configurable:!0,get:function(){return s(this).size}}),r},setStrong:function(t,e,i){var n=e+" Iterator",r=AO(e),o=AO(n);TO(t,e,(function(t,e){IO(this,{type:n,target:t,state:r(t),kind:e,last:void 0})}),(function(){for(var t=o(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?MO("keys"==e?i.key:"values"==e?i.value:[i.key,i.value],!1):(t.target=void 0,MO(void 0,!0))}),i?"entries":"values",!i,!0),OO(e)}};yO("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),LO);var NO=fe.Map;!function(t){t.exports=NO}(PM);var RO=n(EM),FO={},jO={get exports(){return FO},set exports(t){FO=t}};yO("Set",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),LO);var YO=fe.Set;!function(t){t.exports=YO}(jO);var HO=n(FO),zO={};!function(t){t.exports=Id}({get exports(){return zO},set exports(t){zO=t}});var BO=n(zO),GO={},WO={get exports(){return GO},set exports(t){GO=t}},VO={},UO=zs;!function(t){t.exports=UO}({get exports(){return VO},set exports(t){VO=t}}),function(t){t.exports=VO}(WO);var XO=n(GO),qO={},$O={get exports(){return qO},set exports(t){qO=t}},ZO=Ba,KO=Math.floor,JO=function(t,e){var i=t.length,n=KO(i/2);return i<8?QO(t,e):tE(t,JO(ZO(t,0,n),e),JO(ZO(t,n),e),e)},QO=function(t,e){for(var i,n,r=t.length,o=1;o0;)t[n]=t[--n];n!==o++&&(t[n]=i)}return t},tE=function(t,e,i,n){for(var r=e.length,o=i.length,s=0,a=0;s3)){if(yE)return!0;if(_E)return _E<603;var t,e,i,n,r="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(n=0;n<47;n++)wE.push({k:e+n,v:i})}for(wE.sort((function(t,e){return e.v-t.v})),n=0;npE(i)?1:-1}}(t)),i=cE(r),n=0;n1?arguments[1]:void 0)}});var jE=yp("Array").some,YE=_e,HE=jE,zE=Array.prototype,BE=function(t){var e=t.some;return t===zE||YE(zE,t)&&e===zE.some?HE:e},GE=BE;!function(t){t.exports=GE}(RE);var WE=n(NE),VE={},UE={get exports(){return VE},set exports(t){VE=t}},XE=yp("Array").keys,qE=At,$E=W,ZE=_e,KE=XE,JE=Array.prototype,QE={DOMTokenList:!0,NodeList:!0},tP=function(t){var e=t.keys;return t===JE||ZE(JE,t)&&e===JE.keys||$E(QE,qE(t))?KE:e};!function(t){t.exports=tP}(UE);var eP=n(VE),iP={},nP={get exports(){return iP},set exports(t){iP=t}},rP=yp("Array").values,oP=At,sP=W,aP=_e,lP=rP,hP=Array.prototype,uP={DOMTokenList:!0,NodeList:!0},cP=function(t){var e=t.values;return t===hP||aP(hP,t)&&e===hP.values||sP(uP,oP(t))?lP:e};!function(t){t.exports=cP}(nP);var dP=n(iP),pP={},fP={get exports(){return pP},set exports(t){pP=t}},mP=yp("Array").entries,vP=At,gP=W,yP=_e,bP=mP,_P=Array.prototype,wP={DOMTokenList:!0,NodeList:!0},kP=function(t){var e=t.entries;return t===_P||yP(_P,t)&&e===_P.entries||gP(wP,vP(t))?bP:e};!function(t){t.exports=kP}(fP);var xP=n(pP),DP={},SP={get exports(){return DP},set exports(t){DP=t}},CP=In,TP=Ni,MP=jf,OP=DD,EP=ue,PP=Kt,IP=Ar,AP=d,LP=be("Reflect","construct"),NP=Object.prototype,RP=[].push,FP=AP((function(){function t(){}return!(LP((function(){}),[],t)instanceof t)})),jP=!AP((function(){LP((function(){}))})),YP=FP||jP;CP({target:"Reflect",stat:!0,forced:YP,sham:YP},{construct:function(t,e){OP(t),EP(e);var i=arguments.length<3?t:OP(arguments[2]);if(jP&&!FP)return LP(t,e,i);if(t==i){switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3])}var n=[null];return TP(RP,n,e),new(TP(MP,t,n))}var r=i.prototype,o=IP(PP(r)?r:NP),s=TP(t,o,e);return PP(s)?s:o}});var HP=fe.Reflect.construct;!function(t){t.exports=HP}(SP);var zP=n(DP);let BP;const GP=new Uint8Array(16);function WP(){if(!BP&&(BP="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!BP))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return BP(GP)}const VP=[];for(let t=0;t<256;++t)VP.push((t+256).toString(16).slice(1));var UP,XP={randomUUID:"undefined"!=typeof crypto&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function qP(t,e,i){if(XP.randomUUID&&!e&&!t)return XP.randomUUID();const n=(t=t||{}).random||(t.rng||WP)();if(n[6]=15&n[6]|64,n[8]=63&n[8]|128,e){i=i||0;for(let t=0;t<16;++t)e[i+t]=n[t];return e}return function(t,e=0){return(VP[t[e+0]]+VP[t[e+1]]+VP[t[e+2]]+VP[t[e+3]]+"-"+VP[t[e+4]]+VP[t[e+5]]+"-"+VP[t[e+6]]+VP[t[e+7]]+"-"+VP[t[e+8]]+VP[t[e+9]]+"-"+VP[t[e+10]]+VP[t[e+11]]+VP[t[e+12]]+VP[t[e+13]]+VP[t[e+14]]+VP[t[e+15]]).toLowerCase()}(n)}function $P(t,e){var i=gf(t);if(Ou){var n=Ou(t);e&&(n=ig(n).call(n,(function(e){return Bu(t,e).enumerable}))),i.push.apply(i,n)}return i}function ZP(t){for(var e=1;e=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function QP(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);ithis.max&&this.flush(),null!=this._timeout&&(clearTimeout(this._timeout),this._timeout=null),this.queue.length>0&&"number"==typeof this.delay&&(this._timeout=Xy((function(){t.flush()}),this.delay))}},{key:"flush",value:function(){var t,e;am(t=Zm(e=this._queue).call(e,0)).call(t,(function(t){t.fn.apply(t.context||t.fn,t.args||[])}))}}],[{key:"extend",value:function(e,i){var n=new t(i);if(void 0!==e.flush)throw new Error("Target object already has a property flush");e.flush=function(){n.flush()};var r=[{name:"flush",original:void 0}];if(i&&i.replace)for(var o=0;or&&(r=l,n=a)}return n}},{key:"min",value:function(t){var e=XO(this._pairs),i=e.next();if(i.done)return null;for(var n=i.value[1],r=t(i.value[1],i.value[0]);!(i=e.next()).done;){var o=Lp(i.value,2),s=o[0],a=o[1],l=t(a,s);lr?1:nr)&&(n=s,r=a)}}catch(t){o.e(t)}finally{o.f()}return n||null}},{key:"min",value:function(t){var e,i,n=null,r=null,o=JP(dP(e=this._data).call(e));try{for(o.s();!(i=o.n()).done;){var s=i.value,a=s[t];"number"==typeof a&&(null==r||a/g,NI=/"/g,RI=/"/g,FI=/&#([a-zA-Z0-9]*);?/gim,jI=/:?/gim,YI=/&newline;?/gim,HI=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a):/gi,zI=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,BI=/u\s*r\s*l\s*\(.*/gi;function GI(t){return t.replace(NI,""")}function WI(t){return t.replace(RI,'"')}function VI(t){return t.replace(FI,(function(t,e){return"x"===e[0]||"X"===e[0]?String.fromCharCode(parseInt(e.substr(1),16)):String.fromCharCode(parseInt(e,10))}))}function UI(t){return t.replace(jI,":").replace(YI," ")}function XI(t){for(var e="",i=0,n=t.length;i0;e--){var i=t[e];if(" "!==i)return"="===i?e:-1}}function rA(t){return function(t){return'"'===t[0]&&'"'===t[t.length-1]||"'"===t[0]&&"'"===t[t.length-1]}(t)?t.substr(1,t.length-2):t}ZI.parseTag=function(t,e,i){var n="",r=0,o=!1,s=!1,a=0,l=t.length,h="",u="";t:for(a=0;a"===c||a===l-1){n+=i(t.slice(r,o)),h=JI(u=t.slice(o,a+1)),n+=e(o,n.length,h,u,QI(u)),r=a+1,o=!1;continue}if('"'===c||"'"===c)for(var d=1,p=t.charAt(a-d);""===p.trim()||"="===p;){if("="===p){s=c;continue t}p=t.charAt(a-++d)}}else if(c===s){s=!1;continue}}return r";var m=function(t){var e=uA.spaceIndex(t);if(-1===e)return{html:"",closing:"/"===t[t.length-2]};var i="/"===(t=uA.trim(t.slice(e+1,-1)))[t.length-1];return i&&(t=uA.trim(t.slice(0,-1))),{html:t,closing:i}}(c),v=i[u],g=hA(m.html,(function(t,e){var i=-1!==uA.indexOf(v,t),n=o(u,t,e,i);return cA(n)?i?(e=a(u,t,e,h))?t+'="'+e+'"':t:cA(n=s(u,t,e,i))?void 0:n:n}));return c="<"+u,g&&(c+=" "+g),m.closing&&(c+=" /"),c+=">"}return cA(f=r(u,c,p))?l(c):f}),l);return u&&(c=u.remove(c)),c};var pA=dA;!function(t,e){var i=pI,n=ZI,r=pA;function o(t,e){return new r(e).process(t)}(e=t.exports=o).filterXSS=o,e.FilterXSS=r,function(){for(var t in i)e[t]=i[t];for(var r in n)e[r]=n[r]}(),"undefined"!=typeof window&&(window.filterXSS=t.exports),"undefined"!=typeof self&&"undefined"!=typeof DedicatedWorkerGlobalScope&&self instanceof DedicatedWorkerGlobalScope&&(self.filterXSS=t.exports)}(dI,cI);var fA=cI;function mA(t,e){var i=gf(t);if(Ou){var n=Ou(t);e&&(n=ig(n).call(n,(function(e){return Bu(t,e).enumerable}))),i.push.apply(i,n)}return i}function vA(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:{start:"Date",end:"Date"},l=t._idProp,h=new sI({fieldId:l}),u=cf(e=function(t){return new eI(t)}(t)).call(e,(function(t){var e;return uM(e=gf(t)).call(e,(function(e,i){return e[i]=_A(t[i],a[i]),e}),{})})).to(h);return u.all().start(),{add:function(){var e;return(e=t.getDataSet()).add.apply(e,arguments)},remove:function(){var e;return(e=t.getDataSet()).remove.apply(e,arguments)},update:function(){var e;return(e=t.getDataSet()).update.apply(e,arguments)},updateOnly:function(){var e;return(e=t.getDataSet()).updateOnly.apply(e,arguments)},clear:function(){var e;return(e=t.getDataSet()).clear.apply(e,arguments)},forEach:Uf(i=am(h)).call(i,h),get:Uf(n=h.get).call(n,h),getIds:Uf(r=h.getIds).call(r,h),off:Uf(o=h.off).call(o,h),on:Uf(s=h.on).call(s,h),get length(){return h.length},idProp:l,type:a,rawDS:t,coercedDS:h,dispose:function(){return u.stop()}}}var kA=function(t){var e=new fA.FilterXSS(t);return function(t){return e.process(t)}},xA=function(t){return t},DA=kA(),SA=vA(vA({},_k),{},{convert:_A,setupXSSProtection:function(t){t&&(!0===t.disabled?(DA=xA,console.warn("You disabled XSS protection for vis-Timeline. I sure hope you know what you're doing!")):t.filterOptions&&(DA=kA(t.filterOptions)))}});Dc(SA,"xss",{get:function(){return DA}});var CA={},TA={get exports(){return CA},set exports(t){CA=t}},MA=D,OA=d,EA=Rt,PA=Sg.trim,IA=gg,AA=y("".charAt),LA=MA.parseFloat,NA=MA.Symbol,RA=NA&&NA.iterator,FA=1/LA(IA+"-0")!=-1/0||RA&&!OA((function(){LA(Object(RA))}))?function(t){var e=PA(EA(t)),i=LA(e);return 0===i&&"-"==AA(e,0)?-0:i}:LA;In({global:!0,forced:parseFloat!=FA},{parseFloat:FA});var jA=fe.parseFloat;!function(t){t.exports=jA}(TA);var YA=n(CA),HA=function(){function t(e,i){Sc(this,t),this.options=null,this.props=null}return Wd(t,[{key:"setOptions",value:function(t){t&&SA.extend(this.options,t)}},{key:"redraw",value:function(){return!1}},{key:"destroy",value:function(){}},{key:"_isResized",value:function(){var t=this.props._previousWidth!==this.props.width||this.props._previousHeight!==this.props.height;return this.props._previousWidth=this.props.width,this.props._previousHeight=this.props.height,t}}]),t}(),zA={},BA={get exports(){return zA},set exports(t){zA=t}},GA=k,WA=Rt,VA=j,UA=RangeError;In({target:"String",proto:!0},{repeat:function(t){var e=WA(VA(this)),i="",n=GA(t);if(n<0||n==1/0)throw UA("Wrong number of repetitions");for(;n>0;(n>>>=1)&&(e+=e))1&n&&(i+=e);return i}});var XA=yp("String").repeat,qA=_e,$A=XA,ZA=String.prototype,KA=function(t){var e=t.repeat;return"string"==typeof t||t===ZA||qA(ZA,t)&&e===ZA.repeat?$A:e},JA=KA;!function(t){t.exports=JA}(BA);var QA=n(zA);function tL(t,e,i){if(i&&!tf(i))return tL(t,e,[i]);if(e.hiddenDates=[],i&&1==tf(i)){for(var n,r=0;r=4*o){var h=0,u=r.clone();switch(QA(i[s])){case"daily":a.day()!=l.day()&&(h=1),a.dayOfYear(n.dayOfYear()),a.year(n.year()),a.subtract(7,"days"),l.dayOfYear(n.dayOfYear()),l.year(n.year()),l.subtract(7-h,"days"),u.add(1,"weeks");break;case"weekly":var c=l.diff(a,"days"),d=a.day();a.date(n.date()),a.month(n.month()),a.year(n.year()),l=a.clone(),a.day(d),l.day(d),l.add(c,"days"),a.subtract(1,"weeks"),l.subtract(1,"weeks"),u.add(1,"weeks");break;case"monthly":a.month()!=l.month()&&(h=1),a.month(n.month()),a.year(n.year()),a.subtract(1,"months"),l.month(n.month()),l.year(n.year()),l.subtract(1,"months"),l.add(h,"months"),u.add(1,"months");break;case"yearly":a.year()!=l.year()&&(h=1),a.year(n.year()),a.subtract(1,"years"),l.year(n.year()),l.subtract(1,"years"),l.add(h,"years"),u.add(1,"years");break;default:return void console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:",QA(i[s]))}for(;a=i[r].start&&i[o].end<=i[r].end?i[o].remove=!0:i[o].start>=i[r].start&&i[o].start<=i[r].end?(i[r].end=i[o].end,i[o].remove=!0):i[o].end>=i[r].start&&i[o].end<=i[r].end&&(i[r].start=i[o].start,i[o].remove=!0));for(r=0;r=s&&rt.range.end){var a={start:t.range.start,end:e};return e=lL(t.options.moment,t.body.hiddenDates,a,e),n=t.range.conversion(i,o),(e.valueOf()-n.offset)*n.scale}return e=lL(t.options.moment,t.body.hiddenDates,t.range,e),n=t.range.conversion(i,o),(e.valueOf()-n.offset)*n.scale}function oL(t,e,i){if(0==t.body.hiddenDates.length){var n=t.range.conversion(i);return new Date(e/n.scale+n.offset)}var r=sL(t.body.hiddenDates,t.range.start,t.range.end),o=(t.range.end-t.range.start-r)*e/i,s=uL(t.body.hiddenDates,t.range,o);return new Date(s+o+t.range.start)}function sL(t,e,i){for(var n=0,r=0;r=e&&s=e&&s<=i&&(n+=s-o)}return n}function lL(t,e,i,n){return n=t(n).toDate().valueOf(),n-=hL(t,e,i,n)}function hL(t,e,i,n){var r=0;n=t(n).toDate().valueOf();for(var o=0;o=i.start&&a=a&&(r+=a-s)}return r}function uL(t,e,i){for(var n=0,r=0,o=e.start,s=0;s=e.start&&l=i)break;n+=l-a}}return n}function cL(t,e,i,n){var r=dL(e,t);return 1==r.hidden?i<0?1==n?r.startDate-(r.endDate-e)-1:r.startDate-1:1==n?r.endDate+(e-r.startDate)+1:r.endDate+1:e}function dL(t,e){for(var i=0;i=n&&t1e3&&(i=1e3),t.body.dom.rollingModeBtn.style.visibility="hidden",t.currentTimeTimer=Xy(e,i)}()}},{key:"stopRolling",value:function(){void 0!==this.currentTimeTimer&&(clearTimeout(this.currentTimeTimer),this.rolling=!1,this.body.dom.rollingModeBtn.style.visibility="visible")}},{key:"setRange",value:function(t,e,i,n,r){i||(i={}),!0!==i.byUser&&(i.byUser=!1);var o=this,s=null!=t?SA.convert(t,"Date").valueOf():null,a=null!=e?SA.convert(e,"Date").valueOf():null;if(this._cancelAnimation(),this.millisecondsPerPixelCache=void 0,i.animation){var l,h=this.start,u=this.end,c="object"===Nd(i.animation)&&"duration"in i.animation?i.animation.duration:500,d="object"===Nd(i.animation)&&"easingFunction"in i.animation?i.animation.easingFunction:"easeInOutQuad",p=SA.easingFunctions[d];if(!p)throw new Error(Up(l="Unknown easing function ".concat(Dy(d),". Choose from: ")).call(l,gf(SA.easingFunctions).join(", ")));var f=Df(),m=!1;return function t(){if(!o.props.touch.dragging){var e=Df()-f,l=p(e/c),d=e>c,g=d||null===s?s:h+(s-h)*l,y=d||null===a?a:u+(a-u)*l;v=o._applyRange(g,y),eL(o.options.moment,o.body,o.options.hiddenDates),m=m||v;var b={start:new Date(o.start),end:new Date(o.end),byUser:i.byUser,event:i.event};if(r&&r(l,v,d),v&&o.body.emitter.emit("rangechange",b),d){if(m&&(o.body.emitter.emit("rangechanged",b),n))return n()}else o.animationTimer=Xy(t,20)}}()}var v=this._applyRange(s,a);if(eL(this.options.moment,this.body,this.options.hiddenDates),v){var g={start:new Date(this.start),end:new Date(this.end),byUser:i.byUser,event:i.event};if(this.body.emitter.emit("rangechange",g),clearTimeout(o.timeoutID),o.timeoutID=Xy((function(){o.body.emitter.emit("rangechanged",g)}),200),n)return n()}}},{key:"getMillisecondsPerPixel",value:function(){return void 0===this.millisecondsPerPixelCache&&(this.millisecondsPerPixelCache=(this.end-this.start)/this.body.dom.center.clientWidth),this.millisecondsPerPixelCache}},{key:"_cancelAnimation",value:function(){this.animationTimer&&(clearTimeout(this.animationTimer),this.animationTimer=null)}},{key:"_applyRange",value:function(t,e){var i,n=null!=t?SA.convert(t,"Date").valueOf():this.start,r=null!=e?SA.convert(e,"Date").valueOf():this.end,o=null!=this.options.max?SA.convert(this.options.max,"Date").valueOf():null,s=null!=this.options.min?SA.convert(this.options.min,"Date").valueOf():null;if(isNaN(n)||null===n)throw new Error('Invalid start "'.concat(t,'"'));if(isNaN(r)||null===r)throw new Error('Invalid end "'.concat(e,'"'));if(ro&&(r=o)),null!==o&&r>o&&(n-=i=r-o,r-=i,null!=s&&n=this.start-.5&&r<=this.end?(n=this.start,r=this.end):(n-=(i=a-(r-n))/2,r+=i/2)}}if(null!==this.options.zoomMax){var l=YA(this.options.zoomMax);l<0&&(l=0),r-n>l&&(this.end-this.start===l&&nthis.end?(n=this.start,r=this.end):(n+=(i=r-n-l)/2,r-=i/2))}var h=this.start!=n||this.end!=r;return n>=this.start&&n<=this.end||r>=this.start&&r<=this.end||this.start>=n&&this.start<=r||this.end>=n&&this.end<=r||this.body.emitter.emit("checkRangedItems"),this.start=n,this.end=r,h}},{key:"getRange",value:function(){return{start:this.start,end:this.end}}},{key:"conversion",value:function(t,e){return i.conversion(this.start,this.end,t,e)}},{key:"_onDragStart",value:function(t){this.deltaDifference=0,this.previousDelta=0,this.options.moveable&&this._isInsideRange(t)&&this.props.touch.allowDragging&&(this.stopRolling(),this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.dragging=!0,this.body.dom.root&&(this.body.dom.root.style.cursor="move"))}},{key:"_onDrag",value:function(t){if(t&&this.props.touch.dragging&&this.options.moveable&&this.props.touch.allowDragging){var e=this.options.direction;vL(e);var i="horizontal"==e?t.deltaX:t.deltaY;i-=this.deltaDifference;var n=this.props.touch.end-this.props.touch.start;n-=sL(this.body.hiddenDates,this.start,this.end);var r,o="horizontal"==e?this.body.domProps.center.width:this.body.domProps.center.height;r=this.options.rtl?i/o*n:-i/o*n;var s=this.props.touch.start+r,a=this.props.touch.end+r,l=cL(this.body.hiddenDates,s,this.previousDelta-i,!0),h=cL(this.body.hiddenDates,a,this.previousDelta-i,!0);if(l!=s||h!=a)return this.deltaDifference+=i,this.props.touch.start=l,this.props.touch.end=h,void this._onDrag(t);this.previousDelta=i,this._applyRange(s,a);var u=new Date(this.start),c=new Date(this.end);this.body.emitter.emit("rangechange",{start:u,end:c,byUser:!0,event:t}),this.body.emitter.emit("panmove")}}},{key:"_onDragEnd",value:function(t){this.props.touch.dragging&&this.options.moveable&&this.props.touch.allowDragging&&(this.props.touch.dragging=!1,this.body.dom.root&&(this.body.dom.root.style.cursor="auto"),this.body.emitter.emit("rangechanged",{start:new Date(this.start),end:new Date(this.end),byUser:!0,event:t}))}},{key:"_onMouseWheel",value:function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail?e=-t.detail/3:t.deltaY&&(e=-t.deltaY/3),!(this.options.zoomKey&&!t[this.options.zoomKey]&&this.options.zoomable||!this.options.zoomable&&this.options.moveable)&&this.options.zoomable&&this.options.moveable&&this._isInsideRange(t)&&e){var i,n,r=this.options.zoomFriction||5;if(i=e<0?1-e/r:1/(1+e/r),this.rolling){var o=this.options.rollingMode&&this.options.rollingMode.offset||.5;n=this.start+(this.end-this.start)*o}else{var s=this.getPointer({x:t.clientX,y:t.clientY},this.body.dom.center);n=this._pointerToDate(s)}this.zoom(i,n,e,t),t.preventDefault()}}},{key:"_onTouch",value:function(t){this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.allowDragging=!0,this.props.touch.center=null,this.props.touch.centerDate=null,this.scaleOffset=0,this.deltaDifference=0,SA.preventDefault(t)}},{key:"_onPinch",value:function(t){if(this.options.zoomable&&this.options.moveable){SA.preventDefault(t),this.props.touch.allowDragging=!1,this.props.touch.center||(this.props.touch.center=this.getPointer(t.center,this.body.dom.center),this.props.touch.centerDate=this._pointerToDate(this.props.touch.center)),this.stopRolling();var e=1/(t.scale+this.scaleOffset),i=this.props.touch.centerDate,n=sL(this.body.hiddenDates,this.start,this.end),r=hL(this.options.moment,this.body.hiddenDates,this,i),o=n-r,s=i-r+(this.props.touch.start-(i-r))*e,a=i+o+(this.props.touch.end-(i+o))*e;this.startToFront=1-e<=0,this.endToFront=e-1<=0;var l=cL(this.body.hiddenDates,s,1-e,!0),h=cL(this.body.hiddenDates,a,e-1,!0);l==s&&h==a||(this.props.touch.start=l,this.props.touch.end=h,this.scaleOffset=1-t.scale,s=l,a=h);var u={animation:!1,byUser:!0,event:t};this.setRange(s,a,u),this.startToFront=!1,this.endToFront=!0}}},{key:"_isInsideRange",value:function(t){var e=t.center?t.center.x:t.clientX,i=this.body.dom.centerContainer.getBoundingClientRect(),n=this.options.rtl?e-i.left:i.right-e,r=this.body.util.toTime(n);return r>=this.start&&r<=this.end}},{key:"_pointerToDate",value:function(t){var e,i=this.options.direction;if(vL(i),"horizontal"==i)return this.body.util.toTime(t.x).valueOf();var n=this.body.domProps.center.height;return e=this.conversion(n),t.y/e.scale+e.offset}},{key:"getPointer",value:function(t,e){var i=e.getBoundingClientRect();return this.options.rtl?{x:i.right-t.x,y:t.y-i.top}:{x:t.x-i.left,y:t.y-i.top}}},{key:"zoom",value:function(t,e,i,n){null==e&&(e=(this.start+this.end)/2);var r=sL(this.body.hiddenDates,this.start,this.end),o=hL(this.options.moment,this.body.hiddenDates,this,e),s=r-o,a=e-o+(this.start-(e-o))*t,l=e+s+(this.end-(e+s))*t;this.startToFront=!(i>0),this.endToFront=!(-i>0);var h=cL(this.body.hiddenDates,a,i,!0),u=cL(this.body.hiddenDates,l,-i,!0);h==a&&u==l||(a=h,l=u);var c={animation:!1,byUser:!0,event:n};this.setRange(a,l,c),this.startToFront=!1,this.endToFront=!0}},{key:"move",value:function(t){var e=this.end-this.start,i=this.start+e*t,n=this.end+e*t;this.start=i,this.end=n}},{key:"moveTo",value:function(t){var e=(this.start+this.end)/2-t,i=this.start-e,n=this.end-e;this.setRange(i,n,{animation:!1,byUser:!0,event:null})}}],[{key:"conversion",value:function(t,e,i,n){return void 0===n&&(n=0),0!=i&&e-t!=0?{offset:t,scale:i/(e-t-n)}:{offset:0,scale:1}}}]),i}(HA);function vL(t){if("horizontal"!=t&&"vertical"!=t)throw new TypeError('Unknown direction "'.concat(t,'". Choose "horizontal" or "vertical".'))}var gL={},yL=fe.setInterval;!function(t){t.exports=yL}({get exports(){return gL},set exports(t){gL=t}});var bL,_L=n(gL),wL=null;"undefined"!=typeof window?bL=function t(e,i){var n=i||{preventDefault:!1};if(e.Manager){var r=e,o=function(e,i){var o=Object.create(n);return i&&r.assign(o,i),t(new r(e,o),o)};return r.assign(o,r),o.Manager=function(e,i){var o=Object.create(n);return i&&r.assign(o,i),t(new r.Manager(e,o),o)},o}var s=Object.create(e),a=e.element;function l(t){return t.match(/[^ ]+/g)}function h(t){if("hammer.input"!==t.type){if(t.srcEvent._handled||(t.srcEvent._handled={}),t.srcEvent._handled[t.type])return;t.srcEvent._handled[t.type]=!0}var e=!1;t.stopPropagation=function(){e=!0};var i=t.srcEvent.stopPropagation.bind(t.srcEvent);"function"==typeof i&&(t.srcEvent.stopPropagation=function(){i(),t.stopPropagation()}),t.firstTarget=wL;for(var n=wL;n&&!e;){var r=n.hammer;if(r)for(var o,s=0;s0?s._handlers[t]=n:(e.off(t,h),delete s._handlers[t]))})),s},s.emit=function(t,i){wL=i.target,e.emit(t,i)},s.destroy=function(){var t=e.element.hammer,i=t.indexOf(s);-1!==i&&t.splice(i,1),t.length||delete e.element.hammer,s._handlers={},e.destroy()},s}(window.Hammer||yw,{preventDefault:"mouse"}):bL=function(){return function(){var t=function(){};return{on:t,off:t,destroy:t,emit:t,get:function(e){return{set:t}}}}()};var kL=bL;function xL(t,e){e.inputHandler=function(t){t.isFirst&&e(t)},t.on("hammer.input",e.inputHandler)}var DL=function(){function t(e,i,n,r,o){Sc(this,t),this.moment=o&&o.moment||hI,this.options=o||{},this.current=this.moment(),this._start=this.moment(),this._end=this.moment(),this.autoScale=!0,this.scale="day",this.step=1,this.setRange(e,i,n),this.switchedDay=!1,this.switchedMonth=!1,this.switchedYear=!1,tf(r)?this.hiddenDates=r:this.hiddenDates=null!=r?[r]:[],this.format=t.FORMAT}return Wd(t,[{key:"setMoment",value:function(t){this.moment=t,this.current=this.moment(this.current.valueOf()),this._start=this.moment(this._start.valueOf()),this._end=this.moment(this._end.valueOf())}},{key:"setFormat",value:function(e){var i=SA.deepExtend({},t.FORMAT);this.format=SA.deepExtend(i,e)}},{key:"setRange",value:function(t,e,i){if(!(t instanceof Date&&e instanceof Date))throw"No legal start or end date in method setRange";this._start=null!=t?this.moment(t.valueOf()):Df(),this._end=null!=e?this.moment(e.valueOf()):Df(),this.autoScale&&this.setMinimumStep(i)}},{key:"start",value:function(){this.current=this._start.clone(),this.roundToMinor()}},{key:"roundToMinor",value:function(){switch("week"==this.scale&&this.current.weekday(0),this.scale){case"year":this.current.year(this.step*Math.floor(this.current.year()/this.step)),this.current.month(0);case"month":this.current.date(1);case"week":case"day":case"weekday":this.current.hours(0);case"hour":this.current.minutes(0);case"minute":this.current.seconds(0);case"second":this.current.milliseconds(0)}if(1!=this.step){var t=this.current.clone();switch(this.scale){case"millisecond":this.current.subtract(this.current.milliseconds()%this.step,"milliseconds");break;case"second":this.current.subtract(this.current.seconds()%this.step,"seconds");break;case"minute":this.current.subtract(this.current.minutes()%this.step,"minutes");break;case"hour":this.current.subtract(this.current.hours()%this.step,"hours");break;case"weekday":case"day":this.current.subtract((this.current.date()-1)%this.step,"day");break;case"week":this.current.subtract(this.current.week()%this.step,"week");break;case"month":this.current.subtract(this.current.month()%this.step,"month");break;case"year":this.current.subtract(this.current.year()%this.step,"year")}t.isSame(this.current)||(this.current=this.moment(cL(this.hiddenDates,this.current.valueOf(),-1,!0)))}}},{key:"hasNext",value:function(){return this.current.valueOf()<=this._end.valueOf()}},{key:"next",value:function(){var t=this.current.valueOf();switch(this.scale){case"millisecond":this.current.add(this.step,"millisecond");break;case"second":this.current.add(this.step,"second");break;case"minute":this.current.add(this.step,"minute");break;case"hour":this.current.add(this.step,"hour"),this.current.month()<6?this.current.subtract(this.current.hours()%this.step,"hour"):this.current.hours()%this.step!=0&&this.current.add(this.step-this.current.hours()%this.step,"hour");break;case"weekday":case"day":this.current.add(this.step,"day");break;case"week":if(0!==this.current.weekday())this.current.weekday(0),this.current.add(this.step,"week");else if(!1===this.options.showMajorLabels)this.current.add(this.step,"week");else{var e=this.current.clone();e.add(1,"week"),e.isSame(this.current,"month")?this.current.add(this.step,"week"):(this.current.add(this.step,"week"),this.current.date(1))}break;case"month":this.current.add(this.step,"month");break;case"year":this.current.add(this.step,"year")}if(1!=this.step)switch(this.scale){case"millisecond":this.current.milliseconds()>0&&this.current.milliseconds()0&&this.current.seconds()0&&this.current.minutes()0&&this.current.hours()0?t.step:1,this.autoScale=!1)}},{key:"setAutoScale",value:function(t){this.autoScale=t}},{key:"setMinimumStep",value:function(t){if(null!=t){var e=31104e6,i=2592e6,n=864e5,r=36e5,o=6e4,s=1e3;1e3*e>t&&(this.scale="year",this.step=1e3),500*e>t&&(this.scale="year",this.step=500),100*e>t&&(this.scale="year",this.step=100),50*e>t&&(this.scale="year",this.step=50),10*e>t&&(this.scale="year",this.step=10),5*e>t&&(this.scale="year",this.step=5),e>t&&(this.scale="year",this.step=1),7776e6>t&&(this.scale="month",this.step=3),i>t&&(this.scale="month",this.step=1),6048e5>t&&this.options.showWeekScale&&(this.scale="week",this.step=1),1728e5>t&&(this.scale="day",this.step=2),n>t&&(this.scale="day",this.step=1),432e5>t&&(this.scale="weekday",this.step=1),144e5>t&&(this.scale="hour",this.step=4),r>t&&(this.scale="hour",this.step=1),9e5>t&&(this.scale="minute",this.step=15),6e5>t&&(this.scale="minute",this.step=10),3e5>t&&(this.scale="minute",this.step=5),o>t&&(this.scale="minute",this.step=1),15e3>t&&(this.scale="second",this.step=15),1e4>t&&(this.scale="second",this.step=10),5e3>t&&(this.scale="second",this.step=5),s>t&&(this.scale="second",this.step=1),200>t&&(this.scale="millisecond",this.step=200),100>t&&(this.scale="millisecond",this.step=100),50>t&&(this.scale="millisecond",this.step=50),10>t&&(this.scale="millisecond",this.step=10),5>t&&(this.scale="millisecond",this.step=5),1>t&&(this.scale="millisecond",this.step=1)}}},{key:"isMajor",value:function(){if(1==this.switchedYear)switch(this.scale){case"year":case"month":case"week":case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedMonth)switch(this.scale){case"week":case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedDay)switch(this.scale){case"millisecond":case"second":case"minute":case"hour":return!0;default:return!1}var t=this.moment(this.current);switch(this.scale){case"millisecond":return 0==t.milliseconds();case"second":return 0==t.seconds();case"minute":return 0==t.hours()&&0==t.minutes();case"hour":return 0==t.hours();case"weekday":case"day":return this.options.showWeekScale?1==t.isoWeekday():1==t.date();case"week":return 1==t.date();case"month":return 0==t.month();default:return!1}}},{key:"getLabelMinor",value:function(t){if(null==t&&(t=this.current),t instanceof Date&&(t=this.moment(t)),"function"==typeof this.format.minorLabels)return this.format.minorLabels(t,this.scale,this.step);var e=this.format.minorLabels[this.scale];return"week"===this.scale&&1===t.date()&&0!==t.weekday()?"":e&&e.length>0?this.moment(t).format(e):""}},{key:"getLabelMajor",value:function(t){if(null==t&&(t=this.current),t instanceof Date&&(t=this.moment(t)),"function"==typeof this.format.majorLabels)return this.format.majorLabels(t,this.scale,this.step);var e=this.format.majorLabels[this.scale];return e&&e.length>0?this.moment(t).format(e):""}},{key:"getClassName",value:function(){var t,e=this.moment,i=this.moment(this.current),n=i.locale?i.locale("en"):i.lang("en"),r=this.step,o=[];function s(t){return t/r%2==0?" vis-even":" vis-odd"}function a(t){return t.isSame(Df(),"day")?" vis-today":t.isSame(e().add(1,"day"),"day")?" vis-tomorrow":t.isSame(e().add(-1,"day"),"day")?" vis-yesterday":""}function l(t){return t.isSame(Df(),"week")?" vis-current-week":""}function h(t){return t.isSame(Df(),"month")?" vis-current-month":""}switch(this.scale){case"millisecond":o.push(a(n)),o.push(s(n.milliseconds()));break;case"second":o.push(a(n)),o.push(s(n.seconds()));break;case"minute":o.push(a(n)),o.push(s(n.minutes()));break;case"hour":o.push(Up(t="vis-h".concat(n.hours())).call(t,4==this.step?"-h"+(n.hours()+4):"")),o.push(a(n)),o.push(s(n.hours()));break;case"weekday":o.push("vis-".concat(n.format("dddd").toLowerCase())),o.push(a(n)),o.push(l(n)),o.push(s(n.date()));break;case"day":o.push("vis-day".concat(n.date())),o.push("vis-".concat(n.format("MMMM").toLowerCase())),o.push(a(n)),o.push(h(n)),o.push(this.step<=2?a(n):""),o.push(this.step<=2?"vis-".concat(n.format("dddd").toLowerCase()):""),o.push(s(n.date()-1));break;case"week":o.push("vis-week".concat(n.format("w"))),o.push(l(n)),o.push(s(n.week()));break;case"month":o.push("vis-".concat(n.format("MMMM").toLowerCase())),o.push(h(n)),o.push(s(n.month()));break;case"year":o.push("vis-year".concat(n.year())),o.push(function(t){return t.isSame(Df(),"year")?" vis-current-year":""}(n)),o.push(s(n.year()))}return ig(o).call(o,String).join(" ")}}],[{key:"snap",value:function(t,e,i){var n=hI(t);if("year"==e){var r=n.year()+Math.round(n.month()/12);n.year(Math.round(r/i)*i),n.month(0),n.date(0),n.hours(0),n.minutes(0),n.seconds(0),n.milliseconds(0)}else if("month"==e)n.date()>15?(n.date(1),n.add(1,"month")):n.date(1),n.hours(0),n.minutes(0),n.seconds(0),n.milliseconds(0);else if("week"==e)n.weekday()>2?(n.weekday(0),n.add(1,"week")):n.weekday(0),n.hours(0),n.minutes(0),n.seconds(0),n.milliseconds(0);else if("day"==e){switch(i){case 5:case 2:n.hours(24*Math.round(n.hours()/24));break;default:n.hours(12*Math.round(n.hours()/12))}n.minutes(0),n.seconds(0),n.milliseconds(0)}else if("weekday"==e){switch(i){case 5:case 2:n.hours(12*Math.round(n.hours()/12));break;default:n.hours(6*Math.round(n.hours()/6))}n.minutes(0),n.seconds(0),n.milliseconds(0)}else if("hour"==e){if(4===i)n.minutes(60*Math.round(n.minutes()/60));else n.minutes(30*Math.round(n.minutes()/30));n.seconds(0),n.milliseconds(0)}else if("minute"==e){switch(i){case 15:case 10:n.minutes(5*Math.round(n.minutes()/5)),n.seconds(0);break;case 5:n.seconds(60*Math.round(n.seconds()/60));break;default:n.seconds(30*Math.round(n.seconds()/30))}n.milliseconds(0)}else if("second"==e)switch(i){case 15:case 10:n.seconds(5*Math.round(n.seconds()/5)),n.milliseconds(0);break;case 5:n.milliseconds(1e3*Math.round(n.milliseconds()/1e3));break;default:n.milliseconds(500*Math.round(n.milliseconds()/500))}else if("millisecond"==e){var o=i>5?i/2:1;n.milliseconds(Math.round(n.milliseconds()/o)*o)}return n}}]),t}();function SL(t,e){void 0===e&&(e={});var i=e.insertAt;if(t&&"undefined"!=typeof document){var n=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===i&&n.firstChild?n.insertBefore(r,n.firstChild):n.appendChild(r),r.styleSheet?r.styleSheet.cssText=t:r.appendChild(document.createTextNode(t))}}DL.FORMAT={minorLabels:{millisecond:"SSS",second:"s",minute:"HH:mm",hour:"HH:mm",weekday:"ddd D",day:"D",week:"w",month:"MMM",year:"YYYY"},majorLabels:{millisecond:"HH:mm:ss",second:"D MMMM HH:mm",minute:"ddd D MMMM",hour:"ddd D MMMM",weekday:"MMMM YYYY",day:"MMMM YYYY",week:"MMMM YYYY",month:"YYYY",year:""}};function CL(t){var e=function(){if("undefined"==typeof Reflect||!zP)return!1;if(zP.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(zP(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=ex(t);if(e){var r=ex(this).constructor;i=zP(n,arguments,r)}else i=n.apply(this,arguments);return $k(this,i)}}SL(".vis-time-axis{overflow:hidden;position:relative}.vis-time-axis.vis-foreground{left:0;top:0;width:100%}.vis-time-axis.vis-background{height:100%;left:0;position:absolute;top:0;width:100%}.vis-time-axis .vis-text{box-sizing:border-box;color:#4d4d4d;overflow:hidden;padding:3px;position:absolute;white-space:nowrap}.vis-time-axis .vis-text.vis-measure{margin-left:0;margin-right:0;padding-left:0;padding-right:0;position:absolute;visibility:hidden}.vis-time-axis .vis-grid.vis-vertical{border-left:1px solid;position:absolute}.vis-time-axis .vis-grid.vis-vertical-rtl{border-right:1px solid;position:absolute}.vis-time-axis .vis-grid.vis-minor{border-color:#e5e5e5}.vis-time-axis .vis-grid.vis-major{border-color:#bfbfbf}");var TL=function(t){qk(i,t);var e=CL(i);function i(t,n){var r;return Sc(this,i),(r=e.call(this)).dom={foreground:null,lines:[],majorTexts:[],minorTexts:[],redundant:{lines:[],majorTexts:[],minorTexts:[]}},r.props={range:{start:0,end:0,minimumStep:0},lineTop:0},r.defaultOptions={orientation:{axis:"bottom"},showMinorLabels:!0,showMajorLabels:!0,showWeekScale:!1,maxMinorChars:7,format:SA.extend({},DL.FORMAT),moment:hI,timeAxis:null},r.options=SA.extend({},r.defaultOptions),r.body=t,r._create(),r.setOptions(n),r}return Wd(i,[{key:"setOptions",value:function(t){t&&(SA.selectiveExtend(["showMinorLabels","showMajorLabels","showWeekScale","maxMinorChars","hiddenDates","timeAxis","moment","rtl"],this.options,t),SA.selectiveDeepExtend(["format"],this.options,t),"orientation"in t&&("string"==typeof t.orientation?this.options.orientation.axis=t.orientation:"object"===Nd(t.orientation)&&"axis"in t.orientation&&(this.options.orientation.axis=t.orientation.axis)),"locale"in t&&("function"==typeof hI.locale?hI.locale(t.locale):hI.lang(t.locale)))}},{key:"_create",value:function(){this.dom.foreground=document.createElement("div"),this.dom.background=document.createElement("div"),this.dom.foreground.className="vis-time-axis vis-foreground",this.dom.background.className="vis-time-axis vis-background"}},{key:"destroy",value:function(){this.dom.foreground.parentNode&&this.dom.foreground.parentNode.removeChild(this.dom.foreground),this.dom.background.parentNode&&this.dom.background.parentNode.removeChild(this.dom.background),this.body=null}},{key:"redraw",value:function(){var t=this.props,e=this.dom.foreground,i=this.dom.background,n="top"==this.options.orientation.axis?this.body.dom.top:this.body.dom.bottom,r=e.parentNode!==n;this._calculateCharSize();var o=this.options.showMinorLabels&&"none"!==this.options.orientation.axis,s=this.options.showMajorLabels&&"none"!==this.options.orientation.axis;t.minorLabelHeight=o?t.minorCharHeight:0,t.majorLabelHeight=s?t.majorCharHeight:0,t.height=t.minorLabelHeight+t.majorLabelHeight,t.width=e.offsetWidth,t.minorLineHeight=this.body.domProps.root.height-t.majorLabelHeight-("top"==this.options.orientation.axis?this.body.domProps.bottom.height:this.body.domProps.top.height),t.minorLineWidth=1,t.majorLineHeight=t.minorLineHeight+t.majorLabelHeight,t.majorLineWidth=1;var a=e.nextSibling,l=i.nextSibling;return e.parentNode&&e.parentNode.removeChild(e),i.parentNode&&i.parentNode.removeChild(i),e.style.height="".concat(this.props.height,"px"),this._repaintLabels(),a?n.insertBefore(e,a):n.appendChild(e),l?this.body.dom.backgroundVertical.insertBefore(i,l):this.body.dom.backgroundVertical.appendChild(i),this._isResized()||r}},{key:"_repaintLabels",value:function(){var t=this.options.orientation.axis,e=SA.convert(this.body.range.start,"Number"),i=SA.convert(this.body.range.end,"Number"),n=this.body.util.toTime((this.props.minorCharWidth||10)*this.options.maxMinorChars).valueOf(),r=n-hL(this.options.moment,this.body.hiddenDates,this.body.range,n);r-=this.body.util.toTime(0).valueOf();var o=new DL(new Date(e),new Date(i),r,this.body.hiddenDates,this.options);o.setMoment(this.options.moment),this.options.format&&o.setFormat(this.options.format),this.options.timeAxis&&o.setScale(this.options.timeAxis),this.step=o;var s,a,l,h,u,c,d=this.dom;d.redundant.lines=d.lines,d.redundant.majorTexts=d.majorTexts,d.redundant.minorTexts=d.minorTexts,d.lines=[],d.majorTexts=[],d.minorTexts=[];var p,f,m,v=0,g=void 0,y=0,b=1e3;for(o.start(),a=o.getCurrent(),h=this.body.util.toScreen(a);o.hasNext()&&y=.4*p;if(this.options.showMinorLabels&&c){var _=this._repaintMinorText(l,o.getLabelMinor(s),t,m);_.style.width="".concat(v,"px")}u&&this.options.showMajorLabels?(l>0&&(null==g&&(g=l),_=this._repaintMajorText(l,o.getLabelMajor(s),t,m)),f=this._repaintMajorLine(l,v,t,m)):c?f=this._repaintMinorLine(l,v,t,m):f&&(f.style.width="".concat(Yg(f.style.width)+v,"px"))}if(y!==b||ML||(console.warn("Something is wrong with the Timeline scale. Limited drawing of grid lines to ".concat(b," lines.")),ML=!0),this.options.showMajorLabels){var w=this.body.util.toTime(0),k=o.getLabelMajor(w),x=k.length*(this.props.majorCharWidth||10)+10;(null==g||x.vis-custom-time-marker{background-color:inherit;color:#fff;cursor:auto;font-size:12px;padding:3px 5px;top:0;white-space:nowrap;z-index:inherit}");var XL=function(t){qk(i,t);var e=UL(i);function i(t,n){var r,o;Sc(this,i),(o=e.call(this)).body=t,o.defaultOptions={moment:hI,locales:VL,locale:"en",id:void 0,title:void 0},o.options=SA.extend({},o.defaultOptions),o.setOptions(n),o.options.locales=SA.extend({},VL,o.options.locales);var s=o.defaultOptions.locales[o.defaultOptions.locale];return am(r=gf(o.options.locales)).call(r,(function(t){o.options.locales[t]=SA.extend({},s,o.options.locales[t])})),n&&null!=n.time?o.customTime=n.time:o.customTime=new Date,o.eventParams={},o._create(),o}return Wd(i,[{key:"setOptions",value:function(t){t&&SA.selectiveExtend(["moment","locale","locales","id","title","rtl","snap"],this.options,t)}},{key:"_create",value:function(){var t,e,i,n=document.createElement("div");n["custom-time"]=this,n.className="vis-custom-time ".concat(this.options.id||""),n.style.position="absolute",n.style.top="0px",n.style.height="100%",this.bar=n;var r=document.createElement("div");function o(t){this.body.range._onMouseWheel(t)}r.style.position="relative",r.style.top="0px",this.options.rtl?r.style.right="-10px":r.style.left="-10px",r.style.height="100%",r.style.width="20px",r.addEventListener?(r.addEventListener("mousewheel",Uf(o).call(o,this),!1),r.addEventListener("DOMMouseScroll",Uf(o).call(o,this),!1)):r.attachEvent("onmousewheel",Uf(o).call(o,this)),n.appendChild(r),this.hammer=new kL(r),this.hammer.on("panstart",Uf(t=this._onDragStart).call(t,this)),this.hammer.on("panmove",Uf(e=this._onDrag).call(e,this)),this.hammer.on("panend",Uf(i=this._onDragEnd).call(i,this)),this.hammer.get("pan").set({threshold:5,direction:kL.DIRECTION_ALL}),this.hammer.get("press").set({time:1e4})}},{key:"destroy",value:function(){this.hide(),this.hammer.destroy(),this.hammer=null,this.body=null}},{key:"redraw",value:function(){var t=this.body.dom.backgroundVertical;this.bar.parentNode!=t&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),t.appendChild(this.bar));var e=this.body.util.toScreen(this.customTime),i=this.options.locales[this.options.locale];i||(this.warned||(console.warn("WARNING: options.locales['".concat(this.options.locale,"'] not found. See https://visjs.github.io/vis-timeline/docs/timeline/#Localization")),this.warned=!0),i=this.options.locales.en);var n,r=this.options.title;void 0===r?r=(r=Up(n="".concat(i.time,": ")).call(n,this.options.moment(this.customTime).format("dddd, MMMM Do YYYY, H:mm:ss"))).charAt(0).toUpperCase()+r.substring(1):"function"==typeof r&&(r=r.call(this,this.customTime));return this.options.rtl?this.bar.style.right="".concat(e,"px"):this.bar.style.left="".concat(e,"px"),this.bar.title=r,!1}},{key:"hide",value:function(){this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar)}},{key:"setCustomTime",value:function(t){this.customTime=SA.convert(t,"Date"),this.redraw()}},{key:"getCustomTime",value:function(){return new Date(this.customTime.valueOf())}},{key:"setCustomMarker",value:function(t,e){var i,n,r=document.createElement("div");(r.className="vis-custom-time-marker",r.innerHTML=SA.xss(t),r.style.position="absolute",e)&&(r.setAttribute("contenteditable","true"),r.addEventListener("pointerdown",(function(){r.focus()})),r.addEventListener("input",Uf(i=this._onMarkerChange).call(i,this)),r.title=t,r.addEventListener("blur",Uf(n=function(t){this.title!=t.target.innerHTML&&(this._onMarkerChanged(t),this.title=t.target.innerHTML)}).call(n,this)));this.bar.appendChild(r)}},{key:"setCustomTitle",value:function(t){this.options.title=t}},{key:"_onDragStart",value:function(t){this.eventParams.dragging=!0,this.eventParams.customTime=this.customTime,t.stopPropagation()}},{key:"_onDrag",value:function(t){if(this.eventParams.dragging){var e=this.options.rtl?-1*t.deltaX:t.deltaX,i=this.body.util.toScreen(this.eventParams.customTime)+e,n=this.body.util.toTime(i),r=this.body.util.getScale(),o=this.body.util.getStep(),s=this.options.snap,a=s?s(n,r,o):n;this.setCustomTime(a),this.body.emitter.emit("timechange",{id:this.options.id,time:new Date(this.customTime.valueOf()),event:t}),t.stopPropagation()}}},{key:"_onDragEnd",value:function(t){this.eventParams.dragging&&(this.body.emitter.emit("timechanged",{id:this.options.id,time:new Date(this.customTime.valueOf()),event:t}),t.stopPropagation())}},{key:"_onMarkerChange",value:function(t){this.body.emitter.emit("markerchange",{id:this.options.id,title:t.target.innerHTML,event:t}),t.stopPropagation()}},{key:"_onMarkerChanged",value:function(t){this.body.emitter.emit("markerchanged",{id:this.options.id,title:t.target.innerHTML,event:t}),t.stopPropagation()}}],[{key:"customTimeFromTarget",value:function(t){for(var e=t.target;e;){if(e.hasOwnProperty("custom-time"))return e["custom-time"];e=e.parentNode}return null}}]),i}(HA);SL("");SL('.vis-current-time{background-color:#ff7f6e;pointer-events:none;width:2px;z-index:1}.vis-rolling-mode-btn{background:#3876c2;border-radius:50%;color:#fff;cursor:pointer;font-size:28px;font-weight:700;height:40px;opacity:.8;position:absolute;right:20px;text-align:center;top:7px;width:40px}.vis-rolling-mode-btn:before{content:"\\26F6"}.vis-rolling-mode-btn:hover{opacity:1}');SL(".vis-panel{box-sizing:border-box;margin:0;padding:0;position:absolute}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right,.vis-panel.vis-top{border:1px #bfbfbf}.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right{border-bottom-style:solid;border-top-style:solid;overflow:hidden}.vis-left.vis-panel.vis-vertical-scroll,.vis-right.vis-panel.vis-vertical-scroll{height:100%;overflow-x:hidden;overflow-y:scroll}.vis-left.vis-panel.vis-vertical-scroll{direction:rtl}.vis-left.vis-panel.vis-vertical-scroll .vis-content,.vis-right.vis-panel.vis-vertical-scroll{direction:ltr}.vis-right.vis-panel.vis-vertical-scroll .vis-content{direction:rtl}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-top{border-left-style:solid;border-right-style:solid}.vis-background{overflow:hidden}.vis-panel>.vis-content{position:relative}.vis-panel .vis-shadow{box-shadow:0 0 10px rgba(0,0,0,.8);height:1px;position:absolute;width:100%}.vis-panel .vis-shadow.vis-top{left:0;top:-1px}.vis-panel .vis-shadow.vis-bottom{bottom:-1px;left:0}");SL(".vis-graph-group0{fill:#4f81bd;fill-opacity:0;stroke-width:2px;stroke:#4f81bd}.vis-graph-group1{fill:#f79646;fill-opacity:0;stroke-width:2px;stroke:#f79646}.vis-graph-group2{fill:#8c51cf;fill-opacity:0;stroke-width:2px;stroke:#8c51cf}.vis-graph-group3{fill:#75c841;fill-opacity:0;stroke-width:2px;stroke:#75c841}.vis-graph-group4{fill:#ff0100;fill-opacity:0;stroke-width:2px;stroke:#ff0100}.vis-graph-group5{fill:#37d8e6;fill-opacity:0;stroke-width:2px;stroke:#37d8e6}.vis-graph-group6{fill:#042662;fill-opacity:0;stroke-width:2px;stroke:#042662}.vis-graph-group7{fill:#00ff26;fill-opacity:0;stroke-width:2px;stroke:#00ff26}.vis-graph-group8{fill:#f0f;fill-opacity:0;stroke-width:2px;stroke:#f0f}.vis-graph-group9{fill:#8f3938;fill-opacity:0;stroke-width:2px;stroke:#8f3938}.vis-timeline .vis-fill{fill-opacity:.1;stroke:none}.vis-timeline .vis-bar{fill-opacity:.5;stroke-width:1px}.vis-timeline .vis-point{stroke-width:2px;fill-opacity:1}.vis-timeline .vis-legend-background{stroke-width:1px;fill-opacity:.9;fill:#fff;stroke:#c2c2c2}.vis-timeline .vis-outline{stroke-width:1px;fill-opacity:1;fill:#fff;stroke:#e5e5e5}.vis-timeline .vis-icon-fill{fill-opacity:.3;stroke:none}");SL(".vis-timeline{border:1px solid #bfbfbf;box-sizing:border-box;margin:0;overflow:hidden;padding:0;position:relative}.vis-loading-screen{height:100%;left:0;position:absolute;top:0;width:100%}");SL(".vis [class*=span]{min-height:0;width:auto}");var qL=function(){function t(){Sc(this,t)}return Wd(t,[{key:"_create",value:function(t){var e,i,n,r=this;this.dom={},this.dom.container=t,this.dom.container.style.position="relative",this.dom.root=document.createElement("div"),this.dom.background=document.createElement("div"),this.dom.backgroundVertical=document.createElement("div"),this.dom.backgroundHorizontal=document.createElement("div"),this.dom.centerContainer=document.createElement("div"),this.dom.leftContainer=document.createElement("div"),this.dom.rightContainer=document.createElement("div"),this.dom.center=document.createElement("div"),this.dom.left=document.createElement("div"),this.dom.right=document.createElement("div"),this.dom.top=document.createElement("div"),this.dom.bottom=document.createElement("div"),this.dom.shadowTop=document.createElement("div"),this.dom.shadowBottom=document.createElement("div"),this.dom.shadowTopLeft=document.createElement("div"),this.dom.shadowBottomLeft=document.createElement("div"),this.dom.shadowTopRight=document.createElement("div"),this.dom.shadowBottomRight=document.createElement("div"),this.dom.rollingModeBtn=document.createElement("div"),this.dom.loadingScreen=document.createElement("div"),this.dom.root.className="vis-timeline",this.dom.background.className="vis-panel vis-background",this.dom.backgroundVertical.className="vis-panel vis-background vis-vertical",this.dom.backgroundHorizontal.className="vis-panel vis-background vis-horizontal",this.dom.centerContainer.className="vis-panel vis-center",this.dom.leftContainer.className="vis-panel vis-left",this.dom.rightContainer.className="vis-panel vis-right",this.dom.top.className="vis-panel vis-top",this.dom.bottom.className="vis-panel vis-bottom",this.dom.left.className="vis-content",this.dom.center.className="vis-content",this.dom.right.className="vis-content",this.dom.shadowTop.className="vis-shadow vis-top",this.dom.shadowBottom.className="vis-shadow vis-bottom",this.dom.shadowTopLeft.className="vis-shadow vis-top",this.dom.shadowBottomLeft.className="vis-shadow vis-bottom",this.dom.shadowTopRight.className="vis-shadow vis-top",this.dom.shadowBottomRight.className="vis-shadow vis-bottom",this.dom.rollingModeBtn.className="vis-rolling-mode-btn",this.dom.loadingScreen.className="vis-loading-screen",this.dom.root.appendChild(this.dom.background),this.dom.root.appendChild(this.dom.backgroundVertical),this.dom.root.appendChild(this.dom.backgroundHorizontal),this.dom.root.appendChild(this.dom.centerContainer),this.dom.root.appendChild(this.dom.leftContainer),this.dom.root.appendChild(this.dom.rightContainer),this.dom.root.appendChild(this.dom.top),this.dom.root.appendChild(this.dom.bottom),this.dom.root.appendChild(this.dom.rollingModeBtn),this.dom.centerContainer.appendChild(this.dom.center),this.dom.leftContainer.appendChild(this.dom.left),this.dom.rightContainer.appendChild(this.dom.right),this.dom.centerContainer.appendChild(this.dom.shadowTop),this.dom.centerContainer.appendChild(this.dom.shadowBottom),this.dom.leftContainer.appendChild(this.dom.shadowTopLeft),this.dom.leftContainer.appendChild(this.dom.shadowBottomLeft),this.dom.rightContainer.appendChild(this.dom.shadowTopRight),this.dom.rightContainer.appendChild(this.dom.shadowBottomRight),this.props={root:{},background:{},centerContainer:{},leftContainer:{},rightContainer:{},center:{},left:{},right:{},top:{},bottom:{},border:{},scrollTop:0,scrollTopMin:0},this.on("rangechange",(function(){!0===r.initialDrawDone&&r._redraw()})),this.on("rangechanged",(function(){r.initialRangeChangeDone||(r.initialRangeChangeDone=!0)})),this.on("touch",Uf(e=this._onTouch).call(e,this)),this.on("panmove",Uf(i=this._onDrag).call(i,this));var o=this;this._origRedraw=Uf(n=this._redraw).call(n,this),this._redraw=SA.throttle(this._origRedraw),this.on("_change",(function(t){o.itemSet&&o.itemSet.initialItemSetDrawn&&t&&1==t.queue?o._redraw():o._origRedraw()})),this.hammer=new kL(this.dom.root);var s=this.hammer.get("pinch").set({enable:!0});s&&function(t){t.getTouchAction=function(){return["pan-y"]}}(s),this.hammer.get("pan").set({threshold:5,direction:kL.DIRECTION_ALL}),this.timelineListeners={};var a,l,h=["tap","doubletap","press","pinch","pan","panstart","panmove","panend"];function u(t){this.isActive()&&this.emit("mousewheel",t);var e=0,i=0;if("detail"in t&&(i=-1*t.detail),"wheelDelta"in t&&(i=t.wheelDelta),"wheelDeltaY"in t&&(i=t.wheelDeltaY),"wheelDeltaX"in t&&(e=-1*t.wheelDeltaX),"axis"in t&&t.axis===t.HORIZONTAL_AXIS&&(e=-1*i,i=0),"deltaY"in t&&(i=-1*t.deltaY),"deltaX"in t&&(e=t.deltaX),t.deltaMode&&(1===t.deltaMode?(e*=40,i*=40):(e*=40,i*=800)),this.options.preferZoom){if(!this.options.zoomKey||t[this.options.zoomKey])return}else if(this.options.zoomKey&&t[this.options.zoomKey])return;if(this.options.verticalScroll||this.options.horizontalScroll)if(this.options.verticalScroll&&Math.abs(i)>=Math.abs(e)){var n=this.props.scrollTop,r=n+i;if(this.isActive())this._setScrollTop(r)!==n&&(this._redraw(),this.emit("scroll",t),t.preventDefault())}else if(this.options.horizontalScroll){var o=(Math.abs(e)>=Math.abs(i)?e:i)/120*(this.range.end-this.range.start)/20,s=this.range.start+o,a=this.range.end+o,l={animation:!1,byUser:!0,event:t};this.range.setRange(s,a,l),t.preventDefault()}}am(h).call(h,(function(t){var e=function(e){o.isActive()&&o.emit(t,e)};o.hammer.on(t,e),o.timelineListeners[t]=e})),xL(this.hammer,(function(t){o.emit("touch",t)})),a=this.hammer,(l=function(t){o.emit("release",t)}).inputHandler=function(t){t.isFinal&&l(t)},a.on("hammer.input",l.inputHandler);var c="onwheel"in document.createElement("div")?"wheel":void 0!==document.onmousewheel?"mousewheel":this.dom.centerContainer.addEventListener?"DOMMouseScroll":"onmousewheel";function d(t){if(o.options.verticalScroll&&(t.preventDefault(),o.isActive())){var e=-t.target.scrollTop;o._setScrollTop(e),o._redraw(),o.emit("scrollSide",t)}}this.dom.top.addEventListener,this.dom.bottom.addEventListener,this.dom.centerContainer.addEventListener(c,Uf(u).call(u,this),!1),this.dom.top.addEventListener(c,Uf(u).call(u,this),!1),this.dom.bottom.addEventListener(c,Uf(u).call(u,this),!1),this.dom.left.parentNode.addEventListener("scroll",Uf(d).call(d,this)),this.dom.right.parentNode.addEventListener("scroll",Uf(d).call(d,this));var p=!1;function f(t){var e;if(t.preventDefault&&(o.emit("dragover",o.getEventProperties(t)),t.preventDefault()),Qg(e=t.target.className).call(e,"timeline")>-1&&!p)return t.dataTransfer.dropEffect="move",p=!0,!1}function m(t){t.preventDefault&&t.preventDefault(),t.stopPropagation&&t.stopPropagation();try{var e=JSON.parse(t.dataTransfer.getData("text"));if(!e||!e.content)return}catch(t){return!1}return p=!1,t.center={x:t.clientX,y:t.clientY},"item"!==e.target?o.itemSet._onAddItem(t):o.itemSet._onDropObjectOnItem(t),o.emit("drop",o.getEventProperties(t)),!1}if(this.dom.center.addEventListener("dragover",Uf(f).call(f,this),!1),this.dom.center.addEventListener("drop",Uf(m).call(m,this),!1),this.customTimes=[],this.touch={},this.redrawCount=0,this.initialDrawDone=!1,this.initialRangeChangeDone=!1,!t)throw new Error("No container provided");t.appendChild(this.dom.root),t.appendChild(this.dom.loadingScreen)}},{key:"setOptions",value:function(t){var e;if(t){if(SA.selectiveExtend(["width","height","minHeight","maxHeight","autoResize","start","end","clickToUse","dataAttributes","hiddenDates","locale","locales","moment","preferZoom","rtl","zoomKey","horizontalScroll","verticalScroll","longSelectPressTime","snap"],this.options,t),this.dom.rollingModeBtn.style.visibility="hidden",this.options.rtl&&(this.dom.container.style.direction="rtl",this.dom.backgroundVertical.className="vis-panel vis-background vis-vertical-rtl"),this.options.verticalScroll&&(this.options.rtl?this.dom.rightContainer.className="vis-panel vis-right vis-vertical-scroll":this.dom.leftContainer.className="vis-panel vis-left vis-vertical-scroll"),"object"!==Nd(this.options.orientation)&&(this.options.orientation={item:void 0,axis:void 0}),"orientation"in t&&("string"==typeof t.orientation?this.options.orientation={item:t.orientation,axis:t.orientation}:"object"===Nd(t.orientation)&&("item"in t.orientation&&(this.options.orientation.item=t.orientation.item),"axis"in t.orientation&&(this.options.orientation.axis=t.orientation.axis))),"both"===this.options.orientation.axis){if(!this.timeAxis2){var i=this.timeAxis2=new TL(this.body);i.setOptions=function(t){var e=t?SA.extend({},t):{};e.orientation="top",TL.prototype.setOptions.call(i,e)},this.components.push(i)}}else if(this.timeAxis2){var n,r,o=Qg(n=this.components).call(n,this.timeAxis2);if(-1!==o)Zm(r=this.components).call(r,o,1);this.timeAxis2.destroy(),this.timeAxis2=null}"function"==typeof t.drawPoints&&(t.drawPoints={onRender:t.drawPoints}),"hiddenDates"in this.options&&tL(this.options.moment,this.body,this.options.hiddenDates),"clickToUse"in t&&(t.clickToUse?this.activator||(this.activator=new EL(this.dom.root)):this.activator&&(this.activator.destroy(),delete this.activator)),this._initAutoResize()}if(am(e=this.components).call(e,(function(e){return e.setOptions(t)})),"configure"in t){var s;this.configurator||(this.configurator=this._createConfigurator()),this.configurator.setOptions(t.configure);var a=SA.deepExtend({},this.options);am(s=this.components).call(s,(function(t){SA.deepExtend(a,t.options)})),this.configurator.setModuleOptions({global:a})}this._redraw()}},{key:"isActive",value:function(){return!this.activator||this.activator.active}},{key:"destroy",value:function(){var t;for(var e in this.setItems(null),this.setGroups(null),this.off(),this._stopAutoResize(),this.dom.root.parentNode&&this.dom.root.parentNode.removeChild(this.dom.root),this.dom=null,this.activator&&(this.activator.destroy(),delete this.activator),this.timelineListeners)this.timelineListeners.hasOwnProperty(e)&&delete this.timelineListeners[e];this.timelineListeners=null,this.hammer&&this.hammer.destroy(),this.hammer=null,am(t=this.components).call(t,(function(t){return t.destroy()})),this.body=null}},{key:"setCustomTime",value:function(t,e){var i,n=ig(i=this.customTimes).call(i,(function(t){return e===t.options.id}));if(0===n.length)throw new Error("No custom time bar found with id ".concat(Dy(e)));n.length>0&&n[0].setCustomTime(t)}},{key:"getCustomTime",value:function(t){var e,i=ig(e=this.customTimes).call(e,(function(e){return e.options.id===t}));if(0===i.length)throw new Error("No custom time bar found with id ".concat(Dy(t)));return i[0].getCustomTime()}},{key:"setCustomTimeMarker",value:function(t,e,i){var n,r=ig(n=this.customTimes).call(n,(function(t){return t.options.id===e}));if(0===r.length)throw new Error("No custom time bar found with id ".concat(Dy(e)));r.length>0&&r[0].setCustomMarker(t,i)}},{key:"setCustomTimeTitle",value:function(t,e){var i,n=ig(i=this.customTimes).call(i,(function(t){return t.options.id===e}));if(0===n.length)throw new Error("No custom time bar found with id ".concat(Dy(e)));if(n.length>0)return n[0].setCustomTitle(t)}},{key:"getEventProperties",value:function(t){return{event:t}}},{key:"addCustomTime",value:function(t,e){var i,n=void 0!==t?SA.convert(t,"Date"):new Date,r=WE(i=this.customTimes).call(i,(function(t){return t.options.id===e}));if(r)throw new Error("A custom time with id ".concat(Dy(e)," already exists"));var o=new XL(this.body,SA.extend({},this.options,{time:n,id:e,snap:this.itemSet?this.itemSet.options.snap:this.options.snap}));return this.customTimes.push(o),this.components.push(o),this._redraw(),e}},{key:"removeCustomTime",value:function(t){var e,i=this,n=ig(e=this.customTimes).call(e,(function(e){return e.options.id===t}));if(0===n.length)throw new Error("No custom time bar found with id ".concat(Dy(t)));am(n).call(n,(function(t){var e,n,r,o;Zm(e=i.customTimes).call(e,Qg(n=i.customTimes).call(n,t),1),Zm(r=i.components).call(r,Qg(o=i.components).call(o,t),1),t.destroy()}))}},{key:"getVisibleItems",value:function(){return this.itemSet&&this.itemSet.getVisibleItems()||[]}},{key:"getItemsAtCurrentTime",value:function(t){return this.time=t,this.itemSet&&this.itemSet.getItemsAtCurrentTime(this.time)||[]}},{key:"getVisibleGroups",value:function(){return this.itemSet&&this.itemSet.getVisibleGroups()||[]}},{key:"fit",value:function(t,e){var i=this.getDataRange();if(null!==i.min||null!==i.max){var n=i.max-i.min,r=new Date(i.min.valueOf()-.01*n),o=new Date(i.max.valueOf()+.01*n),s=!t||void 0===t.animation||t.animation;this.range.setRange(r,o,{animation:s},e)}}},{key:"getDataRange",value:function(){throw new Error("Cannot invoke abstract method getDataRange")}},{key:"setWindow",value:function(t,e,i,n){var r,o;"function"==typeof arguments[2]&&(n=arguments[2],i={}),1==arguments.length?(r=void 0===(o=arguments[0]).animation||o.animation,this.range.setRange(o.start,o.end,{animation:r})):2==arguments.length&&"function"==typeof arguments[1]?(n=arguments[1],r=void 0===(o=arguments[0]).animation||o.animation,this.range.setRange(o.start,o.end,{animation:r},n)):(r=!i||void 0===i.animation||i.animation,this.range.setRange(t,e,{animation:r},n))}},{key:"moveTo",value:function(t,e,i){"function"==typeof arguments[1]&&(i=arguments[1],e={});var n=this.range.end-this.range.start,r=SA.convert(t,"Date").valueOf(),o=r-n/2,s=r+n/2,a=!e||void 0===e.animation||e.animation;this.range.setRange(o,s,{animation:a},i)}},{key:"getWindow",value:function(){var t=this.range.getRange();return{start:new Date(t.start),end:new Date(t.end)}}},{key:"zoomIn",value:function(t,e,i){if(!(!t||t<0||t>1)){"function"==typeof arguments[1]&&(i=arguments[1],e={});var n=this.getWindow(),r=n.start.valueOf(),o=n.end.valueOf(),s=o-r,a=(s-s/(1+t))/2,l=r+a,h=o-a;this.setWindow(l,h,e,i)}}},{key:"zoomOut",value:function(t,e,i){if(!(!t||t<0||t>1)){"function"==typeof arguments[1]&&(i=arguments[1],e={});var n=this.getWindow(),r=n.start.valueOf(),o=n.end.valueOf(),s=o-r,a=r-s*t/2,l=o+s*t/2;this.setWindow(a,l,e,i)}}},{key:"redraw",value:function(){this._redraw()}},{key:"_redraw",value:function(){var t;this.redrawCount++;var e=this.dom;if(e&&e.container&&0!=e.root.offsetWidth){var i=!1,n=this.options,r=this.props;eL(this.options.moment,this.body,this.options.hiddenDates),"top"==n.orientation?(SA.addClassName(e.root,"vis-top"),SA.removeClassName(e.root,"vis-bottom")):(SA.removeClassName(e.root,"vis-top"),SA.addClassName(e.root,"vis-bottom")),n.rtl?(SA.addClassName(e.root,"vis-rtl"),SA.removeClassName(e.root,"vis-ltr")):(SA.addClassName(e.root,"vis-ltr"),SA.removeClassName(e.root,"vis-rtl")),e.root.style.maxHeight=SA.option.asSize(n.maxHeight,""),e.root.style.minHeight=SA.option.asSize(n.minHeight,""),e.root.style.width=SA.option.asSize(n.width,"");var o=e.root.offsetWidth;r.border.left=1,r.border.right=1,r.border.top=1,r.border.bottom=1,r.center.height=e.center.offsetHeight,r.left.height=e.left.offsetHeight,r.right.height=e.right.offsetHeight,r.top.height=e.top.clientHeight||-r.border.top,r.bottom.height=Math.round(e.bottom.getBoundingClientRect().height)||e.bottom.clientHeight||-r.border.bottom;var s=Math.max(r.left.height,r.center.height,r.right.height),a=r.top.height+s+r.bottom.height+r.border.top+r.border.bottom;e.root.style.height=SA.option.asSize(n.height,"".concat(a,"px")),r.root.height=e.root.offsetHeight,r.background.height=r.root.height;var l=r.root.height-r.top.height-r.bottom.height;r.centerContainer.height=l,r.leftContainer.height=l,r.rightContainer.height=r.leftContainer.height,r.root.width=o,r.background.width=r.root.width,this.initialDrawDone||(r.scrollbarWidth=SA.getScrollBarWidth());var h=e.leftContainer.clientWidth,u=e.rightContainer.clientWidth;n.verticalScroll?n.rtl?(r.left.width=h||-r.border.left,r.right.width=u+r.scrollbarWidth||-r.border.right):(r.left.width=h+r.scrollbarWidth||-r.border.left,r.right.width=u||-r.border.right):(r.left.width=h||-r.border.left,r.right.width=u||-r.border.right),this._setDOM();var c=this._updateScrollTop();"top"!=n.orientation.item&&(c+=Math.max(r.centerContainer.height-r.center.height-r.border.top-r.border.bottom,0)),e.center.style.transform="translateY(".concat(c,"px)");var d=0==r.scrollTop?"hidden":"",p=r.scrollTop==r.scrollTopMin?"hidden":"";e.shadowTop.style.visibility=d,e.shadowBottom.style.visibility=p,e.shadowTopLeft.style.visibility=d,e.shadowBottomLeft.style.visibility=p,e.shadowTopRight.style.visibility=d,e.shadowBottomRight.style.visibility=p,n.verticalScroll&&(e.rightContainer.className="vis-panel vis-right vis-vertical-scroll",e.leftContainer.className="vis-panel vis-left vis-vertical-scroll",e.shadowTopRight.style.visibility="hidden",e.shadowBottomRight.style.visibility="hidden",e.shadowTopLeft.style.visibility="hidden",e.shadowBottomLeft.style.visibility="hidden",e.left.style.top="0px",e.right.style.top="0px"),(!n.verticalScroll||r.center.heightr.centerContainer.height;this.hammer.get("pan").set({direction:f?kL.DIRECTION_ALL:kL.DIRECTION_HORIZONTAL}),this.hammer.get("press").set({time:this.options.longSelectPressTime}),am(t=this.components).call(t,(function(t){i=t.redraw()||i}));if(i){if(this.redrawCount<5)return void this.body.emitter.emit("_change");console.log("WARNING: infinite loop in redraw?")}else this.redrawCount=0;this.body.emitter.emit("changed")}}},{key:"_setDOM",value:function(){var t=this.props,e=this.dom;t.leftContainer.width=t.left.width,t.rightContainer.width=t.right.width;var i=t.root.width-t.left.width-t.right.width;t.center.width=i,t.centerContainer.width=i,t.top.width=i,t.bottom.width=i,e.background.style.height="".concat(t.background.height,"px"),e.backgroundVertical.style.height="".concat(t.background.height,"px"),e.backgroundHorizontal.style.height="".concat(t.centerContainer.height,"px"),e.centerContainer.style.height="".concat(t.centerContainer.height,"px"),e.leftContainer.style.height="".concat(t.leftContainer.height,"px"),e.rightContainer.style.height="".concat(t.rightContainer.height,"px"),e.background.style.width="".concat(t.background.width,"px"),e.backgroundVertical.style.width="".concat(t.centerContainer.width,"px"),e.backgroundHorizontal.style.width="".concat(t.background.width,"px"),e.centerContainer.style.width="".concat(t.center.width,"px"),e.top.style.width="".concat(t.top.width,"px"),e.bottom.style.width="".concat(t.bottom.width,"px"),e.background.style.left="0",e.background.style.top="0",e.backgroundVertical.style.left="".concat(t.left.width+t.border.left,"px"),e.backgroundVertical.style.top="0",e.backgroundHorizontal.style.left="0",e.backgroundHorizontal.style.top="".concat(t.top.height,"px"),e.centerContainer.style.left="".concat(t.left.width,"px"),e.centerContainer.style.top="".concat(t.top.height,"px"),e.leftContainer.style.left="0",e.leftContainer.style.top="".concat(t.top.height,"px"),e.rightContainer.style.left="".concat(t.left.width+t.center.width,"px"),e.rightContainer.style.top="".concat(t.top.height,"px"),e.top.style.left="".concat(t.left.width,"px"),e.top.style.top="0",e.bottom.style.left="".concat(t.left.width,"px"),e.bottom.style.top="".concat(t.top.height+t.centerContainer.height,"px"),e.center.style.left="0",e.left.style.left="0",e.right.style.left="0"}},{key:"setCurrentTime",value:function(t){if(!this.currentTime)throw new Error("Option showCurrentTime must be true");this.currentTime.setCurrentTime(t)}},{key:"getCurrentTime",value:function(){if(!this.currentTime)throw new Error("Option showCurrentTime must be true");return this.currentTime.getCurrentTime()}},{key:"_toTime",value:function(t){return oL(this,t,this.props.center.width)}},{key:"_toGlobalTime",value:function(t){return oL(this,t,this.props.root.width)}},{key:"_toScreen",value:function(t){return rL(this,t,this.props.center.width)}},{key:"_toGlobalScreen",value:function(t){return rL(this,t,this.props.root.width)}},{key:"_initAutoResize",value:function(){1==this.options.autoResize?this._startAutoResize():this._stopAutoResize()}},{key:"_startAutoResize",value:function(){var t=this;this._stopAutoResize(),this._onResize=function(){if(1==t.options.autoResize){if(t.dom.root){var e=t.dom.root.offsetHeight,i=t.dom.root.offsetWidth;i==t.props.lastWidth&&e==t.props.lastHeight||(t.props.lastWidth=i,t.props.lastHeight=e,t.props.scrollbarWidth=SA.getScrollBarWidth(),t.body.emitter.emit("_change"))}}else t._stopAutoResize()},SA.addEventListener(window,"resize",this._onResize),t.dom.root&&(t.props.lastWidth=t.dom.root.offsetWidth,t.props.lastHeight=t.dom.root.offsetHeight),this.watchTimer=_L(this._onResize,1e3)}},{key:"_stopAutoResize",value:function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0),this._onResize&&(SA.removeEventListener(window,"resize",this._onResize),this._onResize=null)}},{key:"_onTouch",value:function(t){this.touch.allowDragging=!0,this.touch.initialScrollTop=this.props.scrollTop}},{key:"_onPinch",value:function(t){this.touch.allowDragging=!1}},{key:"_onDrag",value:function(t){if(t&&this.touch.allowDragging){var e=t.deltaY,i=this._getScrollTop(),n=this._setScrollTop(this.touch.initialScrollTop+e);this.options.verticalScroll&&(this.dom.left.parentNode.scrollTop=-this.props.scrollTop,this.dom.right.parentNode.scrollTop=-this.props.scrollTop),n!=i&&this.emit("verticalDrag")}}},{key:"_setScrollTop",value:function(t){return this.props.scrollTop=t,this._updateScrollTop(),this.props.scrollTop}},{key:"_updateScrollTop",value:function(){var t=Math.min(this.props.centerContainer.height-this.props.border.top-this.props.border.bottom-this.props.center.height,0);return t!=this.props.scrollTopMin&&("top"!=this.options.orientation.item&&(this.props.scrollTop+=t-this.props.scrollTopMin),this.props.scrollTopMin=t),this.props.scrollTop>0&&(this.props.scrollTop=0),this.props.scrollTop1e3&&(i=1e3),t.redraw(),t.body.emitter.emit("currentTimeTick"),t.currentTimeTimer=Xy(e,i)}()}},{key:"stop",value:function(){void 0!==this.currentTimeTimer&&(clearTimeout(this.currentTimeTimer),delete this.currentTimeTimer)}},{key:"setCurrentTime",value:function(t){var e=SA.convert(t,"Date").valueOf(),i=Df();this.offset=e-i,this.redraw()}},{key:"getCurrentTime",value:function(){return new Date(Df()+this.offset)}}]),i}(HA),KL={},JL={get exports(){return KL},set exports(t){KL=t}},QL=In,tN=Sl.find,eN="find",iN=!0;eN in[]&&Array(1)[eN]((function(){iN=!1})),QL({target:"Array",proto:!0,forced:iN},{find:function(t){return tN(this,t,arguments.length>1?arguments[1]:void 0)}});var nN=yp("Array").find,rN=_e,oN=nN,sN=Array.prototype,aN=function(t){var e=t.find;return t===sN||rN(sN,t)&&e===sN.find?oN:e},lN=aN;!function(t){t.exports=lN}(JL);var hN=n(KL),uN={},cN={get exports(){return uN},set exports(t){uN=t}},dN=In,pN=Sl.findIndex,fN="findIndex",mN=!0;fN in[]&&Array(1)[fN]((function(){mN=!1})),dN({target:"Array",proto:!0,forced:mN},{findIndex:function(t){return pN(this,t,arguments.length>1?arguments[1]:void 0)}});var vN=yp("Array").findIndex,gN=_e,yN=vN,bN=Array.prototype,_N=function(t){var e=t.findIndex;return t===bN||gN(bN,t)&&e===bN.findIndex?yN:e},wN=_N;!function(t){t.exports=wN}(cN);var kN=n(uN);function xN(t,e){var i=void 0!==Fp&&Ea(t)||t["@@iterator"];if(!i){if(tf(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return DN(t,e);var n=qp(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return sa(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return DN(t,e)}(t))||e&&t&&"number"==typeof t.length){i&&(t=i);var n=0,r=function(){};return{s:r,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function DN(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);ie.index?1:t.indexi[a].index&&(i[o].top+=i[a].height);for(var l=t[o],h=0;he}),m),Zm(p).call(p,m,0,t),m++}};for(v.s();!(c=v.n()).done;)g()}catch(t){v.e(t)}finally{v.f()}f=null;var y=null;m=0;for(var b=0,_=0,w=0,k=function(){var t,n,r=d.shift();r.top=s(r);var u=l(r),c=h(r);null!==f&&uc&&(_=function(t,e,n,r){n||(n=0);r||(r=t.length);for(i=r-1;i>=n;i--)if(e(t[i]))return i;return n-1}(p,(function(t){return c+SN>=l(t)}),b,horizontalOVerlapEndIndex)+1);for(var v,g,k,x=LE(t=ig(n=qp(p).call(p,b,_)).call(n,(function(t){return ul(t)}))).call(t,(function(t,e){return t.top-e.top})),D=0;Dg.top&&(r.top=S.top+S.height+e.vertical)}o(r)&&(m=LN(p,(function(t){return l(t)-SN>u}),m),Zm(p).call(p,m,0,r),m++);var C=r.top+r.height;if(C>w&&(w=C),a&&a())return{v:null}};d.length>0;){var x=k();if("object"===Nd(x))return x.v}return w}function LN(t,e,i){var n;i||(i=0);var r=kN(n=qp(t).call(t,i)).call(n,e);return-1===r?t.length:r+i}var NN=Object.freeze({__proto__:null,nostack:EN,orderByEnd:TN,orderByStart:CN,stack:MN,stackSubgroups:PN,stackSubgroupsWithInnerStack:IN,substack:ON}),RN="__background__",FN=function(){function t(e,i,n){var r=this;if(Sc(this,t),this.groupId=e,this.subgroups={},this.subgroupStack={},this.subgroupStackAll=!1,this.subgroupVisibility={},this.doInnerStack=!1,this.shouldBailStackItems=!1,this.subgroupIndex=0,this.subgroupOrderer=i&&i.subgroupOrder,this.itemSet=n,this.isVisible=null,this.stackDirty=!0,this._disposeCallbacks=[],i&&i.nestedGroups&&(this.nestedGroups=i.nestedGroups,0==i.showNested?this.showNested=!1:this.showNested=!0),i&&i.subgroupStack)if("boolean"==typeof i.subgroupStack)this.doInnerStack=i.subgroupStack,this.subgroupStackAll=i.subgroupStack;else for(var o in i.subgroupStack)this.subgroupStack[o]=i.subgroupStack[o],this.doInnerStack=this.doInnerStack||i.subgroupStack[o];i&&i.heightMode?this.heightMode=i.heightMode:this.heightMode=n.options.groupHeightMode,this.nestedInGroup=null,this.dom={},this.props={label:{width:0,height:0}},this.className=null,this.items={},this.visibleItems=[],this.itemsInRange=[],this.orderedItems={byStart:[],byEnd:[]},this.checkRangedItems=!1;var s=function(){r.checkRangedItems=!0};this.itemSet.body.emitter.on("checkRangedItems",s),this._disposeCallbacks.push((function(){r.itemSet.body.emitter.off("checkRangedItems",s)})),this._create(),this.setData(i)}return Wd(t,[{key:"_create",value:function(){var t=document.createElement("div");this.itemSet.options.groupEditable.order?t.className="vis-label draggable":t.className="vis-label",this.dom.label=t;var e=document.createElement("div");e.className="vis-inner",t.appendChild(e),this.dom.inner=e;var i=document.createElement("div");i.className="vis-group",i["vis-group"]=this,this.dom.foreground=i,this.dom.background=document.createElement("div"),this.dom.background.className="vis-group",this.dom.axis=document.createElement("div"),this.dom.axis.className="vis-group",this.dom.marker=document.createElement("div"),this.dom.marker.style.visibility="hidden",this.dom.marker.style.position="absolute",this.dom.marker.innerHTML="",this.dom.background.appendChild(this.dom.marker)}},{key:"setData",value:function(t){if(!this.itemSet.groupTouchParams.isDragging){var e,i,n;if(t&&t.subgroupVisibility)for(var r in t.subgroupVisibility)this.subgroupVisibility[r]=t.subgroupVisibility[r];if(this.itemSet.options&&this.itemSet.options.groupTemplate)e=(i=Uf(n=this.itemSet.options.groupTemplate).call(n,this))(t,this.dom.inner);else e=t&&t.content;if(e instanceof Element){for(;this.dom.inner.firstChild;)this.dom.inner.removeChild(this.dom.inner.firstChild);this.dom.inner.appendChild(e)}else e instanceof Object&&e.isReactComponent||(e instanceof Object?i(t,this.dom.inner):this.dom.inner.innerHTML=null!=e?SA.xss(e):SA.xss(this.groupId||""));this.dom.label.title=t&&t.title||"",this.dom.inner.firstChild?SA.removeClassName(this.dom.inner,"vis-hidden"):SA.addClassName(this.dom.inner,"vis-hidden"),t&&t.nestedGroups?(this.nestedGroups&&this.nestedGroups==t.nestedGroups||(this.nestedGroups=t.nestedGroups),void 0===t.showNested&&void 0!==this.showNested||(0==t.showNested?this.showNested=!1:this.showNested=!0),SA.addClassName(this.dom.label,"vis-nesting-group"),this.showNested?(SA.removeClassName(this.dom.label,"collapsed"),SA.addClassName(this.dom.label,"expanded")):(SA.removeClassName(this.dom.label,"expanded"),SA.addClassName(this.dom.label,"collapsed"))):this.nestedGroups&&(this.nestedGroups=null,SA.removeClassName(this.dom.label,"collapsed"),SA.removeClassName(this.dom.label,"expanded"),SA.removeClassName(this.dom.label,"vis-nesting-group")),t&&(t.treeLevel||t.nestedInGroup)?(SA.addClassName(this.dom.label,"vis-nested-group"),t.treeLevel?SA.addClassName(this.dom.label,"vis-group-level-"+t.treeLevel):SA.addClassName(this.dom.label,"vis-group-level-unknown-but-gte1")):SA.addClassName(this.dom.label,"vis-group-level-0");var o=t&&t.className||null;o!=this.className&&(this.className&&(SA.removeClassName(this.dom.label,this.className),SA.removeClassName(this.dom.foreground,this.className),SA.removeClassName(this.dom.background,this.className),SA.removeClassName(this.dom.axis,this.className)),SA.addClassName(this.dom.label,o),SA.addClassName(this.dom.foreground,o),SA.addClassName(this.dom.background,o),SA.addClassName(this.dom.axis,o),this.className=o),this.style&&(SA.removeCssText(this.dom.label,this.style),this.style=null),t&&t.style&&(SA.addCssText(this.dom.label,t.style),this.style=t.style)}}},{key:"getLabelWidth",value:function(){return this.props.label.width}},{key:"_didMarkerHeightChange",value:function(){var t=this.dom.marker.clientHeight;if(t!=this.lastMarkerHeight){this.lastMarkerHeight=t;var e={},i=0;if(am(SA).call(SA,this.items,(function(t,n){if(t.dirty=!0,t.displayed){e[n]=t.redraw(!0),i=e[n].length}})),i>0)for(var n=function(t){am(SA).call(SA,e,(function(e){e[t]()}))},r=0;ri.bailTimeMs&&(i.userBailFunction&&null==this.itemSet.userContinueNotBail?i.userBailFunction((function(e){t.itemSet.userContinueNotBail=e,n=!e})):n=0==t.itemSet.userContinueNotBail)}return n}},{key:"_redrawItems",value:function(t,e,i,n){var r=this;if(t||this.stackDirty||this.isVisible&&!e){var o,s,a,l,h,u,c={byEnd:ig(o=this.orderedItems.byEnd).call(o,(function(t){return!t.isCluster})),byStart:ig(s=this.orderedItems.byStart).call(s,(function(t){return!t.isCluster}))},d={byEnd:Np(new HO(ig(a=cf(l=this.orderedItems.byEnd).call(l,(function(t){return t.cluster}))).call(a,(function(t){return!!t})))),byStart:Np(new HO(ig(h=cf(u=this.orderedItems.byStart).call(u,(function(t){return t.cluster}))).call(h,(function(t){return!!t}))))},p=function(){var t,e,i,o=r._updateItemsInRange(c,ig(t=r.visibleItems).call(t,(function(t){return!t.isCluster})),n),s=r._updateClustersInRange(d,ig(e=r.visibleItems).call(e,(function(t){return t.isCluster})),n);return Up(i=[]).call(i,Np(o),Np(s))},f=function(t){var e={},i=function(i){var n,o=ig(n=r.visibleItems).call(n,(function(t){return t.data.subgroup===i}));e[i]=t?LE(o).call(o,(function(e,i){return t(e.data,i.data)})):o};for(var n in r.subgroups)i(n);return e};if("function"==typeof this.itemSet.options.order){var m=this;if(this.doInnerStack&&this.itemSet.options.stackSubgroups){IN(f(this.itemSet.options.order),i,this.subgroups),this.visibleItems=p(),this._updateSubGroupHeights(i)}else{var v,g,y,b;this.visibleItems=p(),this._updateSubGroupHeights(i);var _=LE(v=ig(g=qp(y=this.visibleItems).call(y)).call(g,(function(t){return t.isCluster||!t.isCluster&&!t.cluster}))).call(v,(function(t,e){return m.itemSet.options.order(t.data,e.data)}));this.shouldBailStackItems=MN(_,i,!0,Uf(b=this._shouldBailItemsRedraw).call(b,this))}}else{var w;if(this.visibleItems=p(),this._updateSubGroupHeights(i),this.itemSet.options.stack)if(this.doInnerStack&&this.itemSet.options.stackSubgroups)IN(f(),i,this.subgroups);else this.shouldBailStackItems=MN(this.visibleItems,i,!0,Uf(w=this._shouldBailItemsRedraw).call(w,this));else EN(this.visibleItems,i,this.subgroups,this.itemSet.options.stackSubgroups)}for(var k=0;k0){var i=this;this._resetSubgroups(),am(SA).call(SA,this.visibleItems,(function(n){void 0!==n.data.subgroup&&(i.subgroups[n.data.subgroup].height=Math.max(i.subgroups[n.data.subgroup].height,n.height+t.item.vertical),i.subgroups[n.data.subgroup].visible=void 0===e.subgroupVisibility[n.data.subgroup]||Boolean(e.subgroupVisibility[n.data.subgroup]))}))}}},{key:"_isGroupVisible",value:function(t,e){return this.top<=t.body.domProps.centerContainer.height-t.body.domProps.scrollTop+e.axis&&this.top+this.height+e.axis>=-t.body.domProps.scrollTop}},{key:"_calculateHeight",value:function(t){var e,i;if((i="fixed"===this.heightMode?SA.toArray(this.items):this.visibleItems).length>0){var n=i[0].top,r=i[0].top+i[0].height;if(am(SA).call(SA,i,(function(t){n=Math.min(n,t.top),r=Math.max(r,t.top+t.height)})),n>t.axis){var o=n-t.axis;r-=o,am(SA).call(SA,i,(function(t){t.top-=o}))}e=Math.ceil(r+t.item.vertical/2),"fitItems"!==this.heightMode&&(e=Math.max(e,this.props.label.height))}else e=this.props.label.height;return e}},{key:"show",value:function(){this.dom.label.parentNode||this.itemSet.dom.labelSet.appendChild(this.dom.label),this.dom.foreground.parentNode||this.itemSet.dom.foreground.appendChild(this.dom.foreground),this.dom.background.parentNode||this.itemSet.dom.background.appendChild(this.dom.background),this.dom.axis.parentNode||this.itemSet.dom.axis.appendChild(this.dom.axis)}},{key:"hide",value:function(){var t=this.dom.label;t.parentNode&&t.parentNode.removeChild(t);var e=this.dom.foreground;e.parentNode&&e.parentNode.removeChild(e);var i=this.dom.background;i.parentNode&&i.parentNode.removeChild(i);var n=this.dom.axis;n.parentNode&&n.parentNode.removeChild(n)}},{key:"add",value:function(t){var e;if(this.items[t.id]=t,t.setParent(this),this.stackDirty=!0,void 0!==t.data.subgroup&&(this._addToSubgroup(t),this.orderSubgroups()),!Yv(e=this.visibleItems).call(e,t)){var i=this.itemSet.body.range;this._checkIfVisible(t,this.visibleItems,i)}}},{key:"_addToSubgroup",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t.data.subgroup;null!=e&&void 0===this.subgroups[e]&&(this.subgroups[e]={height:0,top:0,start:t.data.start,end:t.data.end||t.data.start,visible:!1,index:this.subgroupIndex,items:[],stack:this.subgroupStackAll||this.subgroupStack[e]||!1},this.subgroupIndex++),new Date(t.data.start)new Date(this.subgroups[e].end)&&(this.subgroups[e].end=i),this.subgroups[e].items.push(t)}},{key:"_updateSubgroupsSizes",value:function(){var t=this;if(t.subgroups){var e=function(){var e,n=t.subgroups[i].items[0].data.end||t.subgroups[i].items[0].data.start,r=t.subgroups[i].items[0].data.start,o=n-1;am(e=t.subgroups[i].items).call(e,(function(t){new Date(t.data.start)new Date(o)&&(o=e)})),t.subgroups[i].start=r,t.subgroups[i].end=new Date(o-1)};for(var i in t.subgroups)e()}}},{key:"orderSubgroups",value:function(){if(void 0!==this.subgroupOrderer){var t=[];if("string"==typeof this.subgroupOrderer){for(var e in this.subgroups)t.push({subgroup:e,sortField:this.subgroups[e].items[0].data[this.subgroupOrderer]});LE(t).call(t,(function(t,e){return t.sortField-e.sortField}))}else if("function"==typeof this.subgroupOrderer){for(var i in this.subgroups)t.push(this.subgroups[i].items[0].data);LE(t).call(t,this.subgroupOrderer)}if(t.length>0)for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:t.data.subgroup;if(null!=e){var i=this.subgroups[e];if(i){var n,r,o=Qg(n=i.items).call(n,t);if(o>=0)Zm(r=i.items).call(r,o,1),i.items.length?this._updateSubgroupsSizes():delete this.subgroups[e]}}}},{key:"removeFromDataSet",value:function(t){this.itemSet.removeItem(t.id)}},{key:"order",value:function(){for(var t=SA.toArray(this.items),e=[],i=[],n=0;n0)for(var u=0;uh})),1==this.checkRangedItems){this.checkRangedItems=!1;for(var d=0;dh}))}for(var f={},m=0,v=0;v0)for(var y=function(t){am(SA).call(SA,f,(function(e){e[t]()}))},b=0;b=0;o--){var s=e[o];if(r(s))break;s.isCluster&&!s.hasItems()||s.cluster||void 0===n[s.id]&&(n[s.id]=!0,i.push(s))}for(var a=t+1;a0)for(var o=0;o0)for(var d=0;d=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function zN(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0){var e=[];if(tf(this.options.dataAttributes))e=this.options.dataAttributes;else{if("all"!=this.options.dataAttributes)return;e=gf(this.data)}var i,n=HN(e);try{for(n.s();!(i=n.n()).done;){var r=i.value,o=this.data[r];null!=o?t.setAttribute("data-".concat(r),o):t.removeAttribute("data-".concat(r))}}catch(t){n.e(t)}finally{n.f()}}}},{key:"_updateStyle",value:function(t){this.style&&(SA.removeCssText(t,this.style),this.style=null),this.data.style&&(SA.addCssText(t,this.data.style),this.style=this.data.style)}},{key:"_contentToString",value:function(t){return"string"==typeof t?t:t&&"outerHTML"in t?t.outerHTML:t}},{key:"_updateEditStatus",value:function(){this.options&&("boolean"==typeof this.options.editable?this.editable={updateTime:this.options.editable,updateGroup:this.options.editable,remove:this.options.editable}:"object"===Nd(this.options.editable)&&(this.editable={},SA.selectiveExtend(["updateTime","updateGroup","remove"],this.editable,this.options.editable))),this.options&&this.options.editable&&!0===this.options.editable.overrideItems||this.data&&("boolean"==typeof this.data.editable?this.editable={updateTime:this.data.editable,updateGroup:this.data.editable,remove:this.data.editable}:"object"===Nd(this.data.editable)&&(this.editable={},SA.selectiveExtend(["updateTime","updateGroup","remove"],this.editable,this.data.editable)))}},{key:"getWidthLeft",value:function(){return 0}},{key:"getWidthRight",value:function(){return 0}},{key:"getTitle",value:function(){var t;return this.options.tooltip&&this.options.tooltip.template?Uf(t=this.options.tooltip.template).call(t,this)(this._getItemData(),this.data):this.data.title}}]),t}();function GN(t){var e=function(){if("undefined"==typeof Reflect||!zP)return!1;if(zP.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(zP(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=ex(t);if(e){var r=ex(this).constructor;i=zP(n,arguments,r)}else i=n.apply(this,arguments);return $k(this,i)}}BN.prototype.stack=!0;var WN=function(t){qk(i,t);var e=GN(i);function i(t,n,r){var o;if(Sc(this,i),(o=e.call(this,t,n,r)).props={dot:{width:0,height:0},line:{width:0,height:0}},t&&null==t.start)throw new Error('Property "start" missing in item '.concat(t));return o}return Wd(i,[{key:"isVisible",value:function(t){if(this.cluster)return!1;var e,i=this.data.align||this.options.align,n=this.width*t.getMillisecondsPerPixel();return e="right"==i?this.data.start.getTime()>t.start&&this.data.start.getTime()-nt.start&&this.data.start.getTime()t.start&&this.data.start.getTime()-n/23&&void 0!==arguments[3]&&arguments[3]?-1*e:e;t.style.transform=void 0!==i?void 0!==e?Up(n="translate(".concat(r,"px, ")).call(n,i,"px)"):"translateY(".concat(i,"px)"):"translateX(".concat(r,"px)")}};e(this.dom.box,this.boxX,this.boxY,t),e(this.dom.dot,this.dotX,this.dotY,t),e(this.dom.line,this.lineX,this.lineY,t)}},{key:"repositionX",value:function(){var t=this.conversion.toScreen(this.data.start),e=void 0===this.data.align?this.options.align:this.data.align,i=this.props.line.width,n=this.props.dot.width;"right"==e?(this.boxX=t-this.width,this.lineX=t-i,this.dotX=t-i/2-n/2):"left"==e?(this.boxX=t,this.lineX=t,this.dotX=t+i/2-n/2):(this.boxX=t-this.width/2,this.lineX=this.options.rtl?t-i:t-i/2,this.dotX=t-n/2),this.options.rtl?this.right=this.boxX:this.left=this.boxX,this.repositionXY()}},{key:"repositionY",value:function(){var t=this.options.orientation.item,e=this.dom.line.style;if("top"==t){var i=this.parent.top+this.top+1;this.boxY=this.top||0,e.height="".concat(i,"px"),e.bottom="",e.top="0"}else{var n=this.parent.itemSet.props.height-this.parent.top-this.parent.height+this.top;this.boxY=this.parent.height-this.top-(this.height||0),e.height="".concat(n,"px"),e.top="",e.bottom="0"}this.dotY=-this.props.dot.height/2,this.repositionXY()}},{key:"getWidthLeft",value:function(){return this.width/2}},{key:"getWidthRight",value:function(){return this.width/2}}]),i}(BN);function VN(t){var e=function(){if("undefined"==typeof Reflect||!zP)return!1;if(zP.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(zP(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=ex(t);if(e){var r=ex(this).constructor;i=zP(n,arguments,r)}else i=n.apply(this,arguments);return $k(this,i)}}var UN=function(t){qk(i,t);var e=VN(i);function i(t,n,r){var o;if(Sc(this,i),(o=e.call(this,t,n,r)).props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0,marginRight:0}},t&&null==t.start)throw new Error('Property "start" missing in item '.concat(t));return o}return Wd(i,[{key:"isVisible",value:function(t){if(this.cluster)return!1;var e=this.width*t.getMillisecondsPerPixel();return this.data.start.getTime()+e>t.start&&this.data.start3&&void 0!==arguments[3]&&arguments[3]?-1*e:e;t.style.transform=void 0!==i?void 0!==e?Up(n="translate(".concat(r,"px, ")).call(n,i,"px)"):"translateY(".concat(i,"px)"):"translateX(".concat(r,"px)")}};e(this.dom.point,this.pointX,this.pointY,t)}},{key:"show",value:function(t){if(!this.displayed)return this.redraw(t)}},{key:"hide",value:function(){this.displayed&&(this.dom.point.parentNode&&this.dom.point.parentNode.removeChild(this.dom.point),this.displayed=!1)}},{key:"repositionX",value:function(){var t=this.conversion.toScreen(this.data.start);this.pointX=t,this.options.rtl?this.right=t-this.props.dot.width:this.left=t-this.props.dot.width,this.repositionXY()}},{key:"repositionY",value:function(){var t=this.options.orientation.item;this.pointY="top"==t?this.top:this.parent.height-this.top-this.height,this.repositionXY()}},{key:"getWidthLeft",value:function(){return this.props.dot.width}},{key:"getWidthRight",value:function(){return this.props.dot.width}}]),i}(BN);function XN(t){var e=function(){if("undefined"==typeof Reflect||!zP)return!1;if(zP.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(zP(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=ex(t);if(e){var r=ex(this).constructor;i=zP(n,arguments,r)}else i=n.apply(this,arguments);return $k(this,i)}}var qN=function(t){qk(i,t);var e=XN(i);function i(t,n,r){var o;if(Sc(this,i),(o=e.call(this,t,n,r)).props={content:{width:0}},o.overflow=!1,t){if(null==t.start)throw new Error('Property "start" missing in item '.concat(t.id));if(null==t.end)throw new Error('Property "end" missing in item '.concat(t.id))}return o}return Wd(i,[{key:"isVisible",value:function(t){return!this.cluster&&(this.data.startt.start)}},{key:"_createDomElement",value:function(){this.dom||(this.dom={},this.dom.box=document.createElement("div"),this.dom.frame=document.createElement("div"),this.dom.frame.className="vis-item-overflow",this.dom.box.appendChild(this.dom.frame),this.dom.visibleFrame=document.createElement("div"),this.dom.visibleFrame.className="vis-item-visible-frame",this.dom.box.appendChild(this.dom.visibleFrame),this.dom.content=document.createElement("div"),this.dom.content.className="vis-item-content",this.dom.frame.appendChild(this.dom.content),this.dom.box["vis-item"]=this,this.dirty=!0)}},{key:"_appendDomElement",value:function(){if(!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!this.dom.box.parentNode){var t=this.parent.dom.foreground;if(!t)throw new Error("Cannot redraw item: parent has no foreground container element");t.appendChild(this.dom.box)}this.displayed=!0}},{key:"_updateDirtyDomComponents",value:function(){if(this.dirty){this._updateContents(this.dom.content),this._updateDataAttributes(this.dom.box),this._updateStyle(this.dom.box);var t=this.editable.updateTime||this.editable.updateGroup,e=(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"")+(t?" vis-editable":" vis-readonly");this.dom.box.className=this.baseClassName+e,this.dom.content.style.maxWidth="none"}}},{key:"_getDomComponentsSizes",value:function(){return this.overflow="hidden"!==window.getComputedStyle(this.dom.frame).overflow,this.whiteSpace="nowrap"!==window.getComputedStyle(this.dom.content).whiteSpace,{content:{width:this.dom.content.offsetWidth},box:{height:this.dom.box.offsetHeight}}}},{key:"_updateDomComponentsSizes",value:function(t){this.props.content.width=t.content.width,this.height=t.box.height,this.dom.content.style.maxWidth="",this.dirty=!1}},{key:"_repaintDomAdditionals",value:function(){this._repaintOnItemUpdateTimeTooltip(this.dom.box),this._repaintDeleteButton(this.dom.box),this._repaintDragCenter(),this._repaintDragLeft(),this._repaintDragRight()}},{key:"redraw",value:function(t){var e,i,n,r,o,s,a=this,l=[Uf(e=this._createDomElement).call(e,this),Uf(i=this._appendDomElement).call(i,this),Uf(n=this._updateDirtyDomComponents).call(n,this),function(){var t;a.dirty&&(o=Uf(t=a._getDomComponentsSizes).call(t,a)())},function(){var t;a.dirty&&Uf(t=a._updateDomComponentsSizes).call(t,a)(o)},Uf(r=this._repaintDomAdditionals).call(r,this)];return t?l:(am(l).call(l,(function(t){s=t()})),s)}},{key:"show",value:function(t){if(!this.displayed)return this.redraw(t)}},{key:"hide",value:function(){if(this.displayed){var t=this.dom.box;t.parentNode&&t.parentNode.removeChild(t),this.displayed=!1}}},{key:"repositionX",value:function(t){var e,i,n=this.parent.width,r=this.conversion.toScreen(this.data.start),o=this.conversion.toScreen(this.data.end),s=void 0===this.data.align?this.options.align:this.data.align;!1===this.data.limitSize||void 0!==t&&!0!==t||(r<-n&&(r=-n),o>2*n&&(o=2*n));var a=Math.max(Math.round(1e3*(o-r))/1e3,1);switch(this.overflow?(this.options.rtl?this.right=r:this.left=r,this.width=a+this.props.content.width,i=this.props.content.width):(this.options.rtl?this.right=r:this.left=r,this.width=a,i=Math.min(o-r,this.props.content.width)),this.options.rtl?this.dom.box.style.transform="translateX(".concat(-1*this.right,"px)"):this.dom.box.style.transform="translateX(".concat(this.left,"px)"),this.dom.box.style.width="".concat(a,"px"),this.whiteSpace&&(this.height=this.dom.box.offsetHeight),s){case"left":this.dom.content.style.transform="translateX(0)";break;case"right":if(this.options.rtl){var l=-1*Math.max(a-i,0);this.dom.content.style.transform="translateX(".concat(l,"px)")}else this.dom.content.style.transform="translateX(".concat(Math.max(a-i,0),"px)");break;case"center":if(this.options.rtl){var h=-1*Math.max((a-i)/2,0);this.dom.content.style.transform="translateX(".concat(h,"px)")}else this.dom.content.style.transform="translateX(".concat(Math.max((a-i)/2,0),"px)");break;default:if(e=this.overflow?o>0?Math.max(-r,0):-i:r<0?-r:0,this.options.rtl){var u=-1*e;this.dom.content.style.transform="translateX(".concat(u,"px)")}else this.dom.content.style.transform="translateX(".concat(e,"px)")}}},{key:"repositionY",value:function(){var t=this.options.orientation.item,e=this.dom.box;e.style.top="".concat("top"==t?this.top:this.parent.height-this.top-this.height,"px")}},{key:"_repaintDragLeft",value:function(){if((this.selected||this.options.itemsAlwaysDraggable.range)&&this.editable.updateTime&&!this.dom.dragLeft){var t=document.createElement("div");t.className="vis-drag-left",t.dragLeftItem=this,this.dom.box.appendChild(t),this.dom.dragLeft=t}else this.selected||this.options.itemsAlwaysDraggable.range||!this.dom.dragLeft||(this.dom.dragLeft.parentNode&&this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft),this.dom.dragLeft=null)}},{key:"_repaintDragRight",value:function(){if((this.selected||this.options.itemsAlwaysDraggable.range)&&this.editable.updateTime&&!this.dom.dragRight){var t=document.createElement("div");t.className="vis-drag-right",t.dragRightItem=this,this.dom.box.appendChild(t),this.dom.dragRight=t}else this.selected||this.options.itemsAlwaysDraggable.range||!this.dom.dragRight||(this.dom.dragRight.parentNode&&this.dom.dragRight.parentNode.removeChild(this.dom.dragRight),this.dom.dragRight=null)}}]),i}(BN);function $N(t){var e=function(){if("undefined"==typeof Reflect||!zP)return!1;if(zP.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(zP(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=ex(t);if(e){var r=ex(this).constructor;i=zP(n,arguments,r)}else i=n.apply(this,arguments);return $k(this,i)}}qN.prototype.baseClassName="vis-item vis-range";var ZN=function(t){qk(i,t);var e=$N(i);function i(t,n,r){var o;if(Sc(this,i),(o=e.call(this,t,n,r)).props={content:{width:0}},o.overflow=!1,t){if(null==t.start)throw new Error('Property "start" missing in item '.concat(t.id));if(null==t.end)throw new Error('Property "end" missing in item '.concat(t.id))}return o}return Wd(i,[{key:"isVisible",value:function(t){return this.data.startt.start}},{key:"_createDomElement",value:function(){this.dom||(this.dom={},this.dom.box=document.createElement("div"),this.dom.frame=document.createElement("div"),this.dom.frame.className="vis-item-overflow",this.dom.box.appendChild(this.dom.frame),this.dom.content=document.createElement("div"),this.dom.content.className="vis-item-content",this.dom.frame.appendChild(this.dom.content),this.dirty=!0)}},{key:"_appendDomElement",value:function(){if(!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!this.dom.box.parentNode){var t=this.parent.dom.background;if(!t)throw new Error("Cannot redraw item: parent has no background container element");t.appendChild(this.dom.box)}this.displayed=!0}},{key:"_updateDirtyDomComponents",value:function(){if(this.dirty){this._updateContents(this.dom.content),this._updateDataAttributes(this.dom.content),this._updateStyle(this.dom.box);var t=(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"");this.dom.box.className=this.baseClassName+t}}},{key:"_getDomComponentsSizes",value:function(){return this.overflow="hidden"!==window.getComputedStyle(this.dom.content).overflow,{content:{width:this.dom.content.offsetWidth}}}},{key:"_updateDomComponentsSizes",value:function(t){this.props.content.width=t.content.width,this.height=0,this.dirty=!1}},{key:"_repaintDomAdditionals",value:function(){}},{key:"redraw",value:function(t){var e,i,n,r,o,s,a=this,l=[Uf(e=this._createDomElement).call(e,this),Uf(i=this._appendDomElement).call(i,this),Uf(n=this._updateDirtyDomComponents).call(n,this),function(){var t;a.dirty&&(o=Uf(t=a._getDomComponentsSizes).call(t,a)())},function(){var t;a.dirty&&Uf(t=a._updateDomComponentsSizes).call(t,a)(o)},Uf(r=this._repaintDomAdditionals).call(r,this)];return t?l:(am(l).call(l,(function(t){s=t()})),s)}},{key:"repositionY",value:function(t){var e,i=this.options.orientation.item;if(void 0!==this.data.subgroup){var n=this.data.subgroup;this.dom.box.style.height="".concat(this.parent.subgroups[n].height,"px"),this.dom.box.style.top="".concat("top"==i?this.parent.top+this.parent.subgroups[n].top:this.parent.top+this.parent.height-this.parent.subgroups[n].top-this.parent.subgroups[n].height,"px"),this.dom.box.style.bottom=""}else this.parent instanceof YN?(e=Math.max(this.parent.height,this.parent.itemSet.body.domProps.center.height,this.parent.itemSet.body.domProps.centerContainer.height),this.dom.box.style.bottom="bottom"==i?"0":"",this.dom.box.style.top="top"==i?"0":""):(e=this.parent.height,this.dom.box.style.top="".concat(this.parent.top,"px"),this.dom.box.style.bottom="");this.dom.box.style.height="".concat(e,"px")}}]),i}(BN);ZN.prototype.baseClassName="vis-item vis-background",ZN.prototype.stack=!1,ZN.prototype.show=qN.prototype.show,ZN.prototype.hide=qN.prototype.hide,ZN.prototype.repositionX=qN.prototype.repositionX;SL("div.vis-tooltip{background-color:#f5f4ed;border:1px solid #808074;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;box-shadow:3px 3px 10px rgba(0,0,0,.2);color:#000;font-family:verdana;font-size:14px;padding:5px;pointer-events:none;position:absolute;visibility:hidden;white-space:nowrap;z-index:5}");var KN=function(){function t(e,i){Sc(this,t),this.container=e,this.overflowMethod=i||"cap",this.x=0,this.y=0,this.padding=5,this.hidden=!1,this.frame=document.createElement("div"),this.frame.className="vis-tooltip",this.container.appendChild(this.frame)}return Wd(t,[{key:"setPosition",value:function(t,e){this.x=Yg(t),this.y=Yg(e)}},{key:"setText",value:function(t){t instanceof Element?(this.frame.innerHTML="",this.frame.appendChild(t)):this.frame.innerHTML=SA.xss(t)}},{key:"show",value:function(t){if(void 0===t&&(t=!0),!0===t){var e=this.frame.clientHeight,i=this.frame.clientWidth,n=this.frame.parentNode.clientHeight,r=this.frame.parentNode.clientWidth,o=0,s=0;if("flip"==this.overflowMethod||"none"==this.overflowMethod){var a=!1,l=!0;"flip"==this.overflowMethod&&(this.y-er-this.padding&&(a=!0)),o=a?this.x-i:this.x,s=l?this.y-e:this.y}else(s=this.y-e)+e+this.padding>n&&(s=n-e-this.padding),sr&&(o=r-i-this.padding),o1?arguments[1]:void 0)}});var eR=yp("Array").every,iR=_e,nR=eR,rR=Array.prototype,oR=function(t){var e=t.every;return t===rR||iR(rR,t)&&e===rR.every?nR:e},sR=oR;!function(t){t.exports=sR}(QN);var aR=n(JN);function lR(t,e){var i=void 0!==Fp&&Ea(t)||t["@@iterator"];if(!i){if(tf(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return hR(t,e);var n=qp(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return sa(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return hR(t,e)}(t))||e&&t&&"number"==typeof t.length){i&&(t=i);var n=0,r=function(){};return{s:r,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function hR(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);it.start&&this.hasItems()}},{key:"getData",value:function(){return{isCluster:!0,id:this.id,items:this.data.items||[],data:this.data}}},{key:"redraw",value:function(t){var e,i,n,r,o,s,a,l,h=[Uf(e=this._createDomElement).call(e,this),Uf(i=this._appendDomElement).call(i,this),Uf(n=this._updateDirtyDomComponents).call(n,this),Uf(r=function(){this.dirty&&(a=this._getDomComponentsSizes())}).call(r,this),Uf(o=function(){var t;this.dirty&&Uf(t=this._updateDomComponentsSizes).call(t,this)(a)}).call(o,this),Uf(s=this._repaintDomAdditionals).call(s,this)];return t?h:(am(h).call(h,(function(t){l=t()})),l)}},{key:"show",value:function(){this.displayed||this.redraw()}},{key:"hide",value:function(){if(this.displayed){var t=this.dom;t.box.parentNode&&t.box.parentNode.removeChild(t.box),this.options.showStipes&&(t.line.parentNode&&t.line.parentNode.removeChild(t.line),t.dot.parentNode&&t.dot.parentNode.removeChild(t.dot)),this.displayed=!1}}},{key:"repositionX",value:function(){var t=this.conversion.toScreen(this.data.start),e=this.data.end?this.conversion.toScreen(this.data.end):0;if(e)this.repositionXWithRanges(t,e);else{var i=void 0===this.data.align?this.options.align:this.data.align;this.repositionXWithoutRanges(t,i)}this.options.showStipes&&(this.dom.line.style.display=this._isStipeVisible()?"block":"none",this.dom.dot.style.display=this._isStipeVisible()?"block":"none",this._isStipeVisible()&&this.repositionStype(t,e))}},{key:"repositionStype",value:function(t,e){this.dom.line.style.display="block",this.dom.dot.style.display="block";var i=this.dom.line.offsetWidth,n=this.dom.dot.offsetWidth;if(e){var r=i+t+(e-t)/2,o=r-n/2,s=this.options.rtl?-1*r:r,a=this.options.rtl?-1*o:o;this.dom.line.style.transform="translateX(".concat(s,"px)"),this.dom.dot.style.transform="translateX(".concat(a,"px)")}else{var l=this.options.rtl?-1*t:t,h=this.options.rtl?-1*(t-n/2):t-n/2;this.dom.line.style.transform="translateX(".concat(l,"px)"),this.dom.dot.style.transform="translateX(".concat(h,"px)")}}},{key:"repositionXWithoutRanges",value:function(t,e){"right"==e?this.options.rtl?(this.right=t-this.width,this.dom.box.style.right=this.right+"px"):(this.left=t-this.width,this.dom.box.style.left=this.left+"px"):"left"==e?this.options.rtl?(this.right=t,this.dom.box.style.right=this.right+"px"):(this.left=t,this.dom.box.style.left=this.left+"px"):this.options.rtl?(this.right=t-this.width/2,this.dom.box.style.right=this.right+"px"):(this.left=t-this.width/2,this.dom.box.style.left=this.left+"px")}},{key:"repositionXWithRanges",value:function(t,e){var i=Math.round(Math.max(e-t+.5,1));this.options.rtl?this.right=t:this.left=t,this.width=Math.max(i,this.minWidth||0),this.options.rtl?this.dom.box.style.right=this.right+"px":this.dom.box.style.left=this.left+"px",this.dom.box.style.width=i+"px"}},{key:"repositionY",value:function(){var t=this.options.orientation.item,e=this.dom.box;if(e.style.top="top"==t?(this.top||0)+"px":(this.parent.height-this.top-this.height||0)+"px",this.options.showStipes){if("top"==t)this.dom.line.style.top="0",this.dom.line.style.height=this.parent.top+this.top+1+"px",this.dom.line.style.bottom="";else{var i=this.parent.itemSet.props.height,n=i-this.parent.top-this.parent.height+this.top;this.dom.line.style.top=i-n+"px",this.dom.line.style.bottom="0"}this.dom.dot.style.top=-this.dom.dot.offsetHeight/2+"px"}}},{key:"getWidthLeft",value:function(){return this.width/2}},{key:"getWidthRight",value:function(){return this.width/2}},{key:"move",value:function(){this.repositionX(),this.repositionY()}},{key:"attach",value:function(){var t,e,i=lR(this.data.uiItems);try{for(i.s();!(e=i.n()).done;){e.value.cluster=this}}catch(t){i.e(t)}finally{i.f()}this.data.items=cf(t=this.data.uiItems).call(t,(function(t){return t.data})),this.attached=!0,this.dirty=!0}},{key:"detach",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(this.hasItems()){var e,i=lR(this.data.uiItems);try{for(i.s();!(e=i.n()).done;){delete e.value.cluster}}catch(t){i.e(t)}finally{i.f()}this.attached=!1,t&&this.group&&(this.group.remove(this),this.group=null),this.data.items=[],this.dirty=!0}}},{key:"_onDoubleClick",value:function(){this._fit()}},{key:"_setupRange",value:function(){var t,e,i,n=cf(t=this.data.uiItems).call(t,(function(t){return{start:t.data.start.valueOf(),end:t.data.end?t.data.end.valueOf():t.data.start.valueOf()}}));this.data.min=Math.min.apply(Math,Np(cf(n).call(n,(function(t){return Math.min(t.start,t.end||t.start)})))),this.data.max=Math.max.apply(Math,Np(cf(n).call(n,(function(t){return Math.max(t.start,t.end||t.start)}))));var r=cf(e=this.data.uiItems).call(e,(function(t){return t.center})),o=uM(r).call(r,(function(t,e){return t+e}),0)/this.data.uiItems.length;WE(i=this.data.uiItems).call(i,(function(t){return t.data.end}))?(this.data.start=new Date(this.data.min),this.data.end=new Date(this.data.max)):(this.data.start=new Date(o),this.data.end=null)}},{key:"_getUiItems",value:function(){var t,e=this;return this.data.uiItems&&this.data.uiItems.length?ig(t=this.data.uiItems).call(t,(function(t){return t.cluster===e})):[]}},{key:"_createDomElement",value:function(){if(!this.dom){var t;if(this.dom={},this.dom.box=document.createElement("DIV"),this.dom.content=document.createElement("DIV"),this.dom.content.className="vis-item-content",this.dom.box.appendChild(this.dom.content),this.options.showStipes&&(this.dom.line=document.createElement("DIV"),this.dom.line.className="vis-cluster-line",this.dom.line.style.display="none",this.dom.dot=document.createElement("DIV"),this.dom.dot.className="vis-cluster-dot",this.dom.dot.style.display="none"),this.options.fitOnDoubleClick)this.dom.box.ondblclick=Uf(t=i.prototype._onDoubleClick).call(t,this);this.dom.box["vis-item"]=this,this.dirty=!0}}},{key:"_appendDomElement",value:function(){if(!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!this.dom.box.parentNode){var t=this.parent.dom.foreground;if(!t)throw new Error("Cannot redraw item: parent has no foreground container element");t.appendChild(this.dom.box)}var e=this.parent.dom.background;if(this.options.showStipes){if(!this.dom.line.parentNode){if(!e)throw new Error("Cannot redraw item: parent has no background container element");e.appendChild(this.dom.line)}if(!this.dom.dot.parentNode){var i=this.parent.dom.axis;if(!e)throw new Error("Cannot redraw item: parent has no axis container element");i.appendChild(this.dom.dot)}}this.displayed=!0}},{key:"_updateDirtyDomComponents",value:function(){if(this.dirty){this._updateContents(this.dom.content),this._updateDataAttributes(this.dom.box),this._updateStyle(this.dom.box);var t=this.baseClassName+" "+(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"")+" vis-readonly";this.dom.box.className="vis-item "+t,this.options.showStipes&&(this.dom.line.className="vis-item vis-cluster-line "+(this.selected?" vis-selected":""),this.dom.dot.className="vis-item vis-cluster-dot "+(this.selected?" vis-selected":"")),this.data.end&&(this.dom.content.style.maxWidth="none")}}},{key:"_getDomComponentsSizes",value:function(){var t={previous:{right:this.dom.box.style.right,left:this.dom.box.style.left},box:{width:this.dom.box.offsetWidth,height:this.dom.box.offsetHeight}};return this.options.showStipes&&(t.dot={height:this.dom.dot.offsetHeight,width:this.dom.dot.offsetWidth},t.line={width:this.dom.line.offsetWidth}),t}},{key:"_updateDomComponentsSizes",value:function(t){this.options.rtl?this.dom.box.style.right="0px":this.dom.box.style.left="0px",this.data.end?this.minWidth=t.box.width:this.width=t.box.width,this.height=t.box.height,this.options.rtl?this.dom.box.style.right=t.previous.right:this.dom.box.style.left=t.previous.left,this.dirty=!1}},{key:"_repaintDomAdditionals",value:function(){this._repaintOnItemUpdateTimeTooltip(this.dom.box)}},{key:"_isStipeVisible",value:function(){return this.minWidth>=this.width||!this.data.end}},{key:"_getFitRange",value:function(){var t=.05*(this.data.max-this.data.min)/2;return{fitStart:this.data.min-t,fitEnd:this.data.max+t}}},{key:"_fit",value:function(){if(this.emitter){var t=this._getFitRange(),e=t.fitStart,i=t.fitEnd,n={start:new Date(e),end:new Date(i),animation:!0};this.emitter.emit("fit",n)}}},{key:"_getItemData",value:function(){return this.data}}]),i}(BN);function dR(t,e){var i=void 0!==Fp&&Ea(t)||t["@@iterator"];if(!i){if(tf(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return pR(t,e);var n=qp(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return sa(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return pR(t,e)}(t))||e&&t&&"number"==typeof t.length){i&&(t=i);var n=0,r=function(){};return{s:r,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function pR(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0){if(e>=1)return[];s=Math.abs(Math.round(Math.log(100/e)/Math.log(2))),a=Math.abs(Math.pow(2,s))}if(this.dataChanged){var l=s!=this.cacheLevel;(!this.applyOnChangedLevel||l)&&(this._dropLevelsCache(),this._filterData())}this.cacheLevel=s;var h=this.cache[s];if(!h){for(var u in h=[],this.groups)if(this.groups.hasOwnProperty(u))for(var c=this.groups[u],d=c.length,p=0;p=0&&f.center-c[v].center=0&&f.center-h[y].centerr){for(var b=m-r+1,_=[],w=p;_.length'+t.length+"",f=fv({},n,this.itemSet.options),m={content:p,title:d,group:e,uiItems:t,eventEmitter:this.itemSet.body.emitter,range:this.itemSet.body.range};return o=this.createClusterItem(m,c,f),e&&(e.add(o),o.group=e),o.attach(),o}},{key:"_dropLevelsCache",value:function(){this.cache={},this.cacheLevel=-1,this.cache[this.cacheLevel]=[]}}]),t}();SL('.vis-itemset{box-sizing:border-box;margin:0;padding:0;position:relative}.vis-itemset .vis-background,.vis-itemset .vis-foreground{height:100%;overflow:visible;position:absolute;width:100%}.vis-axis{height:0;left:0;position:absolute;width:100%;z-index:1}.vis-foreground .vis-group{border-bottom:1px solid #bfbfbf;box-sizing:border-box;position:relative}.vis-foreground .vis-group:last-child{border-bottom:none}.vis-nesting-group{cursor:pointer}.vis-label.vis-nested-group.vis-group-level-unknown-but-gte1{background:#f5f5f5}.vis-label.vis-nested-group.vis-group-level-0{background-color:#fff}.vis-ltr .vis-label.vis-nested-group.vis-group-level-0 .vis-inner{padding-left:0}.vis-rtl .vis-label.vis-nested-group.vis-group-level-0 .vis-inner{padding-right:0}.vis-label.vis-nested-group.vis-group-level-1{background-color:rgba(0,0,0,.05)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-1 .vis-inner{padding-left:15px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-1 .vis-inner{padding-right:15px}.vis-label.vis-nested-group.vis-group-level-2{background-color:rgba(0,0,0,.1)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-2 .vis-inner{padding-left:30px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-2 .vis-inner{padding-right:30px}.vis-label.vis-nested-group.vis-group-level-3{background-color:rgba(0,0,0,.15)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-3 .vis-inner{padding-left:45px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-3 .vis-inner{padding-right:45px}.vis-label.vis-nested-group.vis-group-level-4{background-color:rgba(0,0,0,.2)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-4 .vis-inner{padding-left:60px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-4 .vis-inner{padding-right:60px}.vis-label.vis-nested-group.vis-group-level-5{background-color:rgba(0,0,0,.25)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-5 .vis-inner{padding-left:75px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-5 .vis-inner{padding-right:75px}.vis-label.vis-nested-group.vis-group-level-6{background-color:rgba(0,0,0,.3)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-6 .vis-inner{padding-left:90px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-6 .vis-inner{padding-right:90px}.vis-label.vis-nested-group.vis-group-level-7{background-color:rgba(0,0,0,.35)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-7 .vis-inner{padding-left:105px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-7 .vis-inner{padding-right:105px}.vis-label.vis-nested-group.vis-group-level-8{background-color:rgba(0,0,0,.4)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-8 .vis-inner{padding-left:120px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-8 .vis-inner{padding-right:120px}.vis-label.vis-nested-group.vis-group-level-9{background-color:rgba(0,0,0,.45)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-9 .vis-inner{padding-left:135px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-9 .vis-inner{padding-right:135px}.vis-label.vis-nested-group{background-color:rgba(0,0,0,.5)}.vis-ltr .vis-label.vis-nested-group .vis-inner{padding-left:150px}.vis-rtl .vis-label.vis-nested-group .vis-inner{padding-right:150px}.vis-group-level-unknown-but-gte1{border:1px solid red}.vis-label.vis-nesting-group:before{display:inline-block;width:15px}.vis-label.vis-nesting-group.expanded:before{content:"\\25BC"}.vis-label.vis-nesting-group.collapsed:before{content:"\\25B6"}.vis-rtl .vis-label.vis-nesting-group.collapsed:before{content:"\\25C0"}.vis-ltr .vis-label:not(.vis-nesting-group):not(.vis-group-level-0){padding-left:15px}.vis-rtl .vis-label:not(.vis-nesting-group):not(.vis-group-level-0){padding-right:15px}.vis-overlay{height:100%;left:0;position:absolute;top:0;width:100%;z-index:10}');function vR(t,e){var i=void 0!==Fp&&Ea(t)||t["@@iterator"];if(!i){if(tf(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return gR(t,e);var n=qp(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return sa(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return gR(t,e)}(t))||e&&t&&"number"==typeof t.length){i&&(t=i);var n=0,r=function(){};return{s:r,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function gR(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0){var n,r=o.groupsData.getDataSet();am(n=r.get()).call(n,(function(t){if(t.nestedGroups){var e;0!=t.showNested&&(t.showNested=!0);var n=[];am(e=t.nestedGroups).call(e,(function(e){var i=r.get(e);i&&(i.nestedInGroup=t.id,0==t.showNested&&(i.visible=!1),n=Up(n).call(n,i))})),r.update(n,i)}}))}},update:function(t,e,i){o._onUpdateGroups(e.items)},remove:function(t,e,i){o._onRemoveGroups(e.items)}},r.items={},r.groups={},r.groupIds=[],r.selection=[],r.popup=null,r.popupTimer=null,r.touchParams={},r.groupTouchParams={group:null,isDragging:!1},r._create(),r.setOptions(n),r.clusters=[],r}return Wd(i,[{key:"_create",value:function(){var t,e,i,n,r,o,s,a,l,h,u,c,d,p,f,m=this,v=document.createElement("div");v.className="vis-itemset",v["vis-itemset"]=this,this.dom.frame=v;var g=document.createElement("div");g.className="vis-background",v.appendChild(g),this.dom.background=g;var y=document.createElement("div");y.className="vis-foreground",v.appendChild(y),this.dom.foreground=y;var b=document.createElement("div");b.className="vis-axis",this.dom.axis=b;var _=document.createElement("div");_.className="vis-labelset",this.dom.labelSet=_,this._updateUngrouped();var w=new YN(_R,null,this);w.show(),this.groups[_R]=w,this.hammer=new kL(this.body.dom.centerContainer),this.hammer.on("hammer.input",(function(t){t.isFirst&&m._onTouch(t)})),this.hammer.on("panstart",Uf(t=this._onDragStart).call(t,this)),this.hammer.on("panmove",Uf(e=this._onDrag).call(e,this)),this.hammer.on("panend",Uf(i=this._onDragEnd).call(i,this)),this.hammer.get("pan").set({threshold:5,direction:kL.ALL}),this.hammer.get("press").set({time:1e4}),this.hammer.on("tap",Uf(n=this._onSelectItem).call(n,this)),this.hammer.on("press",Uf(r=this._onMultiSelectItem).call(r,this)),this.hammer.get("press").set({time:1e4}),this.hammer.on("doubletap",Uf(o=this._onAddItem).call(o,this)),this.options.rtl?this.groupHammer=new kL(this.body.dom.rightContainer):this.groupHammer=new kL(this.body.dom.leftContainer),this.groupHammer.on("tap",Uf(s=this._onGroupClick).call(s,this)),this.groupHammer.on("panstart",Uf(a=this._onGroupDragStart).call(a,this)),this.groupHammer.on("panmove",Uf(l=this._onGroupDrag).call(l,this)),this.groupHammer.on("panend",Uf(h=this._onGroupDragEnd).call(h,this)),this.groupHammer.get("pan").set({threshold:5,direction:kL.DIRECTION_VERTICAL}),this.body.dom.centerContainer.addEventListener("mouseover",Uf(u=this._onMouseOver).call(u,this)),this.body.dom.centerContainer.addEventListener("mouseout",Uf(c=this._onMouseOut).call(c,this)),this.body.dom.centerContainer.addEventListener("mousemove",Uf(d=this._onMouseMove).call(d,this)),this.body.dom.centerContainer.addEventListener("contextmenu",Uf(p=this._onDragEnd).call(p,this)),this.body.dom.centerContainer.addEventListener("mousewheel",Uf(f=this._onMouseWheel).call(f,this)),this.show()}},{key:"setOptions",value:function(t){var e=this;if(t){var i,n;SA.selectiveExtend(["type","rtl","align","order","stack","stackSubgroups","selectable","multiselect","sequentialSelection","multiselectPerGroup","longSelectPressTime","groupOrder","dataAttributes","template","groupTemplate","visibleFrameTemplate","hide","snap","groupOrderSwap","showTooltips","tooltip","tooltipOnItemUpdateTime","groupHeightMode","onTimeout"],this.options,t),"itemsAlwaysDraggable"in t&&("boolean"==typeof t.itemsAlwaysDraggable?(this.options.itemsAlwaysDraggable.item=t.itemsAlwaysDraggable,this.options.itemsAlwaysDraggable.range=!1):"object"===Nd(t.itemsAlwaysDraggable)&&(SA.selectiveExtend(["item","range"],this.options.itemsAlwaysDraggable,t.itemsAlwaysDraggable),this.options.itemsAlwaysDraggable.item||(this.options.itemsAlwaysDraggable.range=!1))),"sequentialSelection"in t&&"boolean"==typeof t.sequentialSelection&&(this.options.sequentialSelection=t.sequentialSelection),"orientation"in t&&("string"==typeof t.orientation?this.options.orientation.item="top"===t.orientation?"top":"bottom":"object"===Nd(t.orientation)&&"item"in t.orientation&&(this.options.orientation.item=t.orientation.item)),"margin"in t&&("number"==typeof t.margin?(this.options.margin.axis=t.margin,this.options.margin.item.horizontal=t.margin,this.options.margin.item.vertical=t.margin):"object"===Nd(t.margin)&&(SA.selectiveExtend(["axis"],this.options.margin,t.margin),"item"in t.margin&&("number"==typeof t.margin.item?(this.options.margin.item.horizontal=t.margin.item,this.options.margin.item.vertical=t.margin.item):"object"===Nd(t.margin.item)&&SA.selectiveExtend(["horizontal","vertical"],this.options.margin.item,t.margin.item)))),am(i=["locale","locales"]).call(i,(function(i){i in t&&(e.options[i]=t[i])})),"editable"in t&&("boolean"==typeof t.editable?(this.options.editable.updateTime=t.editable,this.options.editable.updateGroup=t.editable,this.options.editable.add=t.editable,this.options.editable.remove=t.editable,this.options.editable.overrideItems=!1):"object"===Nd(t.editable)&&SA.selectiveExtend(["updateTime","updateGroup","add","remove","overrideItems"],this.options.editable,t.editable)),"groupEditable"in t&&("boolean"==typeof t.groupEditable?(this.options.groupEditable.order=t.groupEditable,this.options.groupEditable.add=t.groupEditable,this.options.groupEditable.remove=t.groupEditable):"object"===Nd(t.groupEditable)&&SA.selectiveExtend(["order","add","remove"],this.options.groupEditable,t.groupEditable));am(n=["onDropObjectOnItem","onAdd","onUpdate","onRemove","onMove","onMoving","onAddGroup","onMoveGroup","onRemoveGroup"]).call(n,(function(i){var n=t[i];if(n){var r;if("function"!=typeof n)throw new Error(Up(r="option ".concat(i," must be a function ")).call(r,i,"(item, callback)"));e.options[i]=n}})),t.cluster?(fv(this.options,{cluster:t.cluster}),this.clusterGenerator||(this.clusterGenerator=new mR(this)),this.clusterGenerator.setItems(this.items,{applyOnChangedLevel:!1}),this.markDirty({refreshItems:!0,restackGroups:!0}),this.redraw()):this.clusterGenerator?(this._detachAllClusters(),this.clusters=[],this.clusterGenerator=null,this.options.cluster=void 0,this.markDirty({refreshItems:!0,restackGroups:!0}),this.redraw()):this.markDirty()}}},{key:"markDirty",value:function(t){this.groupIds=[],t&&(t.refreshItems&&am(SA).call(SA,this.items,(function(t){t.dirty=!0,t.displayed&&t.redraw()})),t.restackGroups&&am(SA).call(SA,this.groups,(function(t,e){e!==_R&&(t.stackDirty=!0)})))}},{key:"destroy",value:function(){this.clearPopupTimer(),this.hide(),this.setItems(null),this.setGroups(null),this.hammer&&this.hammer.destroy(),this.groupHammer&&this.groupHammer.destroy(),this.hammer=null,this.body=null,this.conversion=null}},{key:"hide",value:function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame),this.dom.axis.parentNode&&this.dom.axis.parentNode.removeChild(this.dom.axis),this.dom.labelSet.parentNode&&this.dom.labelSet.parentNode.removeChild(this.dom.labelSet)}},{key:"show",value:function(){this.dom.frame.parentNode||this.body.dom.center.appendChild(this.dom.frame),this.dom.axis.parentNode||this.body.dom.backgroundVertical.appendChild(this.dom.axis),this.dom.labelSet.parentNode||(this.options.rtl?this.body.dom.right.appendChild(this.dom.labelSet):this.body.dom.left.appendChild(this.dom.labelSet))}},{key:"setPopupTimer",value:function(t){if(this.clearPopupTimer(),t){var e=this.options.tooltip.delay||"number"==typeof this.options.tooltip.delay?this.options.tooltip.delay:500;this.popupTimer=Xy((function(){t.show()}),e)}}},{key:"clearPopupTimer",value:function(){null!=this.popupTimer&&(clearTimeout(this.popupTimer),this.popupTimer=null)}},{key:"setSelection",value:function(t){var e;null==t&&(t=[]),tf(t)||(t=[t]);var i,n=ig(e=this.selection).call(e,(function(e){return-1===Qg(t).call(t,e)})),r=vR(n);try{for(r.s();!(i=r.n()).done;){var o=i.value,s=this.getItemById(o);s&&s.unselect()}}catch(t){r.e(t)}finally{r.f()}this.selection=Np(t);var a,l=vR(t);try{for(l.s();!(a=l.n()).done;){var h=a.value,u=this.getItemById(h);u&&u.select()}}catch(t){l.e(t)}finally{l.f()}}},{key:"getSelection",value:function(){var t;return Up(t=this.selection).call(t,[])}},{key:"getVisibleItems",value:function(){var t,e,i=this.body.range.getRange();this.options.rtl?(t=this.body.util.toScreen(i.start),e=this.body.util.toScreen(i.end)):(e=this.body.util.toScreen(i.start),t=this.body.util.toScreen(i.end));var n=[];for(var r in this.groups)if(this.groups.hasOwnProperty(r)){var o,s=this.groups[r],a=vR(s.isVisible?s.visibleItems:[]);try{for(a.s();!(o=a.n()).done;){var l=o.value;this.options.rtl?l.rightt&&n.push(l.id):l.lefte&&n.push(l.id)}}catch(t){a.e(t)}finally{a.f()}}return n}},{key:"getItemsAtCurrentTime",value:function(t){var e,i;this.options.rtl?(e=this.body.util.toScreen(t),i=this.body.util.toScreen(t)):(i=this.body.util.toScreen(t),e=this.body.util.toScreen(t));var n=[];for(var r in this.groups)if(this.groups.hasOwnProperty(r)){var o,s=this.groups[r],a=vR(s.isVisible?s.visibleItems:[]);try{for(a.s();!(o=a.n()).done;){var l=o.value;this.options.rtl?l.righte&&n.push(l.id):l.lefti&&n.push(l.id)}}catch(t){a.e(t)}finally{a.f()}}return n}},{key:"getVisibleGroups",value:function(){var t=[];for(var e in this.groups){if(this.groups.hasOwnProperty(e))this.groups[e].isVisible&&t.push(e)}return t}},{key:"getItemById",value:function(t){var e;return this.items[t]||hN(e=this.clusters).call(e,(function(e){return e.id===t}))}},{key:"_deselect",value:function(t){for(var e=this.selection,i=0,n=e.length;i0){for(var _={},w=function(t){am(SA).call(SA,y,(function(e,i){_[i]=e[t]()}))},k=0;k1&&void 0!==arguments[1]?arguments[1]:void 0;if(t&&t.nestedGroups){var i=this.groupsData.getDataSet();t.showNested=null!=e?!!e:!t.showNested;var n=i.get(t.groupId);n.showNested=t.showNested;for(var r,o=t.nestedGroups,s=o;s.length>0;){var a=s;s=[];for(var l=0;l0&&(o=Up(o).call(o,s))}if(n.showNested){for(var u=i.get(n.nestedGroups),c=0;c0&&(null==d.showNested||1==d.showNested)&&u.push.apply(u,Np(i.get(d.nestedGroups)))}r=cf(u).call(u,(function(t){return null==t.visible&&(t.visible=!0),t.visible=!!n.showNested,t}))}else{var p;r=cf(p=i.get(o)).call(p,(function(t){return null==t.visible&&(t.visible=!0),t.visible=!!n.showNested,t}))}i.update(Up(r).call(r,n)),n.showNested?(SA.removeClassName(t.dom.label,"collapsed"),SA.addClassName(t.dom.label,"expanded")):(SA.removeClassName(t.dom.label,"expanded"),SA.addClassName(t.dom.label,"collapsed"))}}},{key:"toggleGroupDragClassName",value:function(t){t.dom.label.classList.toggle("vis-group-is-dragging"),t.dom.foreground.classList.toggle("vis-group-is-dragging")}},{key:"_onGroupDragStart",value:function(t){this.groupTouchParams.isDragging||this.options.groupEditable.order&&(this.groupTouchParams.group=this.groupFromTarget(t),this.groupTouchParams.group&&(t.stopPropagation(),this.groupTouchParams.isDragging=!0,this.toggleGroupDragClassName(this.groupTouchParams.group),this.groupTouchParams.originalOrder=this.groupsData.getIds({order:this.options.groupOrder})))}},{key:"_onGroupDrag",value:function(t){if(this.options.groupEditable.order&&this.groupTouchParams.group){t.stopPropagation();var e=this.groupsData.getDataSet(),i=this.groupFromTarget(t);if(i&&i.height!=this.groupTouchParams.group.height){var n=i.topr)return}}if(i&&i!=this.groupTouchParams.group){var l=e.get(i.groupId),h=e.get(this.groupTouchParams.group.groupId);h&&l&&(this.options.groupOrderSwap(h,l,e),e.update(h),e.update(l));var u=e.getIds({order:this.options.groupOrder});if(!SA.equalArray(u,this.groupTouchParams.originalOrder))for(var c=this.groupTouchParams.originalOrder,d=this.groupTouchParams.group.groupId,p=Math.min(c.length,u.length),f=0,m=0,v=0;f=p)break;if(u[f+m]==d)m=1;else if(c[f+v]==d)v=1;else{var g=Qg(u).call(u,c[f+v]),y=e.get(u[f+m]),b=e.get(c[f+v]);this.options.groupOrderSwap(y,b,e),e.update(y),e.update(b);var _=u[f+m];u[f+m]=c[f+v],u[g]=_,f++}}}}}},{key:"_onGroupDragEnd",value:function(t){if(this.groupTouchParams.isDragging=!1,this.options.groupEditable.order&&this.groupTouchParams.group){t.stopPropagation();var e=this,i=e.groupTouchParams.group.groupId,n=e.groupsData.getDataSet(),r=SA.extend({},n.get(i));e.options.onMoveGroup(r,(function(t){if(t)t[n._idProp]=i,n.update(t);else{var r=n.getIds({order:e.options.groupOrder});if(!SA.equalArray(r,e.groupTouchParams.originalOrder))for(var o=e.groupTouchParams.originalOrder,s=Math.min(o.length,r.length),a=0;a=s)break;var l=Qg(r).call(r,o[a]),h=n.get(r[a]),u=n.get(o[a]);e.options.groupOrderSwap(h,u,n),n.update(h),n.update(u);var c=r[a];r[a]=o[a],r[l]=c,a++}}})),e.body.emitter.emit("groupDragged",{groupId:i}),this.toggleGroupDragClassName(this.groupTouchParams.group),this.groupTouchParams.group=null}}},{key:"_onSelectItem",value:function(t){if(this.options.selectable){var e=t.srcEvent&&(t.srcEvent.ctrlKey||t.srcEvent.metaKey),i=t.srcEvent&&t.srcEvent.shiftKey;if(e||i)this._onMultiSelectItem(t);else{var n=this.getSelection(),r=this.itemFromTarget(t),o=r&&r.selectable?[r.id]:[];this.setSelection(o);var s=this.getSelection();(s.length>0||n.length>0)&&this.body.emitter.emit("select",{items:s,event:t})}}}},{key:"_onMouseOver",value:function(t){var e=this.itemFromTarget(t);if(e&&e!==this.itemFromRelatedTarget(t)){var i=e.getTitle();if(this.options.showTooltips&&i){null==this.popup&&(this.popup=new KN(this.body.dom.root,this.options.tooltip.overflowMethod||"flip")),this.popup.setText(i);var n=this.body.dom.centerContainer,r=n.getBoundingClientRect();this.popup.setPosition(t.clientX-r.left+n.offsetLeft,t.clientY-r.top+n.offsetTop),this.setPopupTimer(this.popup)}else this.clearPopupTimer(),null!=this.popup&&this.popup.hide();this.body.emitter.emit("itemover",{item:e.id,event:t})}}},{key:"_onMouseOut",value:function(t){var e=this.itemFromTarget(t);e&&(e!==this.itemFromRelatedTarget(t)&&(this.clearPopupTimer(),null!=this.popup&&this.popup.hide(),this.body.emitter.emit("itemout",{item:e.id,event:t})))}},{key:"_onMouseMove",value:function(t){if(this.itemFromTarget(t)&&(null!=this.popupTimer&&this.setPopupTimer(this.popup),this.options.showTooltips&&this.options.tooltip.followMouse&&this.popup&&!this.popup.hidden)){var e=this.body.dom.centerContainer,i=e.getBoundingClientRect();this.popup.setPosition(t.clientX-i.left+e.offsetLeft,t.clientY-i.top+e.offsetTop),this.popup.show()}}},{key:"_onMouseWheel",value:function(t){this.touchParams.itemIsDragging&&this._onDragEnd(t)}},{key:"_onUpdateItem",value:function(t){if(this.options.selectable&&(this.options.editable.updateTime||this.options.editable.updateGroup)){var e=this;if(t){var i=e.itemsData.get(t.id);this.options.onUpdate(i,(function(t){t&&e.itemsData.update(t)}))}}}},{key:"_onDropObjectOnItem",value:function(t){var e=this.itemFromTarget(t),i=JSON.parse(t.dataTransfer.getData("text"));this.options.onDropObjectOnItem(i,e)}},{key:"_onAddItem",value:function(t){if(this.options.selectable&&this.options.editable.add){var e,i,n=this,r=this.options.snap||null,o=this.dom.frame.getBoundingClientRect(),s=this.options.rtl?o.right-t.center.x:t.center.x-o.left,a=this.body.util.toTime(s),l=this.body.util.getScale(),h=this.body.util.getStep();"drop"==t.type?((i=JSON.parse(t.dataTransfer.getData("text"))).content=i.content?i.content:"new item",i.start=i.start?i.start:r?r(a,l,h):a,i.type=i.type||"box",i[this.itemsData.idProp]=i.id||qP(),"range"!=i.type||i.end||(e=this.body.util.toTime(s+this.props.width/5),i.end=r?r(e,l,h):e)):((i={start:r?r(a,l,h):a,content:"new item"})[this.itemsData.idProp]=qP(),"range"===this.options.type&&(e=this.body.util.toTime(s+this.props.width/5),i.end=r?r(e,l,h):e));var u=this.groupFromTarget(t);u&&(i.group=u.groupId),i=this._cloneItemData(i),this.options.onAdd(i,(function(e){e&&(n.itemsData.add(e),"drop"==t.type&&n.setSelection([e.id]))}))}}},{key:"_onMultiSelectItem",value:function(t){var e=this;if(this.options.selectable){var n=this.itemFromTarget(t);if(n){var r=this.options.multiselect?this.getSelection():[];if((t.srcEvent&&t.srcEvent.shiftKey||!1||this.options.sequentialSelection)&&this.options.multiselect){var o=this.itemsData.get(n.id).group,s=void 0;this.options.multiselectPerGroup&&r.length>0&&(s=this.itemsData.get(r[0]).group),this.options.multiselectPerGroup&&null!=s&&s!=o||r.push(n.id);var a=i._getItemRange(this.itemsData.get(r));if(!this.options.multiselectPerGroup||s==o)for(var l in r=[],this.items)if(this.items.hasOwnProperty(l)){var h=this.items[l],u=h.data.start,c=void 0!==h.data.end?h.data.end:u;!(u>=a.min&&c<=a.max)||this.options.multiselectPerGroup&&s!=this.itemsData.get(h.id).group||h instanceof ZN||r.push(h.id)}}else{var d=Qg(r).call(r,n.id);-1==d?r.push(n.id):Zm(r).call(r,d,1)}var p=ig(r).call(r,(function(t){return e.getItemById(t).selectable}));this.setSelection(p),this.body.emitter.emit("select",{items:this.getSelection(),event:t})}}}},{key:"itemFromElement",value:function(t){for(var e=t;e;){if(e.hasOwnProperty("vis-item"))return e["vis-item"];e=e.parentNode}return null}},{key:"itemFromTarget",value:function(t){return this.itemFromElement(t.target)}},{key:"itemFromRelatedTarget",value:function(t){return this.itemFromElement(t.relatedTarget)}},{key:"groupFromTarget",value:function(t){var e=t.center?t.center.y:t.clientY,i=this.groupIds;i.length<=0&&this.groupsData&&(i=this.groupsData.getIds({order:this.options.groupOrder}));for(var n=0;n=a.top&&ea.top)return o}else if(0===n&&ee)&&(e=t.end):(null==e||t.start>e)&&(e=t.start)})),{min:i,max:e}}},{key:"itemSetFromTarget",value:function(t){for(var e=t.target;e;){if(e.hasOwnProperty("vis-itemset"))return e["vis-itemset"];e=e.parentNode}return null}}]),i}(HA);wR.types={background:ZN,box:WN,range:qN,point:UN},wR.prototype._onAdd=wR.prototype._onUpdate;var kR,xR=!1,DR="background: #FFeeee; color: #dd0000",SR=function(){function t(){Sc(this,t)}return Wd(t,null,[{key:"validate",value:function(e,i,n){xR=!1,kR=i;var r=i;return void 0!==n&&(r=i[n]),t.parse(e,r,[]),xR}},{key:"parse",value:function(e,i,n){for(var r in e)e.hasOwnProperty(r)&&t.check(r,e,i,n)}},{key:"check",value:function(e,i,n,r){if(void 0!==n[e]||void 0!==n.__any__){var o=e,s=!0;void 0===n[e]&&void 0!==n.__any__&&(o="__any__",s="object"===t.getType(i[e]));var a=n[o];s&&void 0!==a.__type__&&(a=a.__type__),t.checkFields(e,i,n,o,a,r)}else t.getSuggestion(e,n,r)}},{key:"checkFields",value:function(e,i,n,r,o,s){var a=function(i){console.log("%c"+i+t.printLocation(s,e),DR)},l=t.getType(i[e]),h=o[l];void 0!==h?"array"===t.getType(h)&&-1===Qg(h).call(h,i[e])?(a('Invalid option detected in "'+e+'". Allowed values are:'+t.print(h)+' not "'+i[e]+'". '),xR=!0):"object"===l&&"__any__"!==r&&(s=SA.copyAndExtendArray(s,e),t.parse(i[e],n[r],s)):void 0===o.any&&(a('Invalid type received for "'+e+'". Expected: '+t.print(gf(o))+". Received ["+l+'] "'+i[e]+'"'),xR=!0)}},{key:"getType",value:function(t){var e=Nd(t);return"object"===e?null===t?"null":t instanceof Boolean?"boolean":t instanceof Number?"number":t instanceof String?"string":tf(t)?"array":t instanceof Date?"date":void 0!==t.nodeType?"dom":!0===t._isAMomentObject?"moment":"object":"number"===e?"number":"boolean"===e?"boolean":"string"===e?"string":void 0===e?"undefined":e}},{key:"getSuggestion",value:function(e,i,n){var r,o=t.findInOptions(e,i,n,!1),s=t.findInOptions(e,kR,[],!0);r=void 0!==o.indexMatch?" in "+t.printLocation(o.path,e,"")+'Perhaps it was incomplete? Did you mean: "'+o.indexMatch+'"?\n\n':s.distance<=4&&o.distance>s.distance?" in "+t.printLocation(o.path,e,"")+"Perhaps it was misplaced? Matching option found at: "+t.printLocation(s.path,s.closestMatch,""):o.distance<=8?'. Did you mean "'+o.closestMatch+'"?'+t.printLocation(o.path,e):". Did you mean one of these: "+t.print(gf(i))+t.printLocation(n,e),console.log('%cUnknown option detected: "'+e+'"'+r,DR),xR=!0}},{key:"findInOptions",value:function(e,i,n){var r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],o=1e9,s="",a=[],l=e.toLowerCase(),h=void 0;for(var u in i){var c=void 0;if(void 0!==i[u].__type__&&!0===r){var d=t.findInOptions(e,i[u],SA.copyAndExtendArray(n,u));o>d.distance&&(s=d.closestMatch,a=d.path,o=d.distance,h=d.indexMatch)}else{var p;-1!==Qg(p=u.toLowerCase()).call(p,l)&&(h=u),o>(c=t.levenshteinDistance(e,u))&&(s=u,a=SA.copyArray(n),o=c)}}return{closestMatch:s,path:a,distance:o,indexMatch:h}}},{key:"printLocation",value:function(t,e){for(var i="\n\n"+(arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Problem value found at: \n")+"options = {\n",n=0;n0&&void 0!==arguments[0]?arguments[0]:1;Sc(this,t),this.pixelRatio=e,this.generated=!1,this.centerCoordinates={x:144.5,y:144.5},this.r=289*.49,this.color={r:255,g:255,b:255,a:1},this.hueCircle=void 0,this.initialColor={r:255,g:255,b:255,a:1},this.previousColor=void 0,this.applied=!1,this.updateCallback=function(){},this.closeCallback=function(){},this._create()}return Wd(t,[{key:"insertTo",value:function(t){void 0!==this.hammer&&(this.hammer.destroy(),this.hammer=void 0),this.container=t,this.container.appendChild(this.frame),this._bindHammer(),this._setSize()}},{key:"setUpdateCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker update callback is not a function.");this.updateCallback=t}},{key:"setCloseCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker closing callback is not a function.");this.closeCallback=t}},{key:"_isColorString",value:function(t){if("string"==typeof t)return NR[t]}},{key:"setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if("none"!==t){var i,n=this._isColorString(t);if(void 0!==n&&(t=n),!0===SA.isString(t)){if(!0===SA.isValidRGB(t)){var r=t.substr(4).substr(0,t.length-5).split(",");i={r:r[0],g:r[1],b:r[2],a:1}}else if(!0===SA.isValidRGBA(t)){var o=t.substr(5).substr(0,t.length-6).split(",");i={r:o[0],g:o[1],b:o[2],a:o[3]}}else if(!0===SA.isValidHex(t)){var s=SA.hexToRGB(t);i={r:s.r,g:s.g,b:s.b,a:1}}}else if(t instanceof Object&&void 0!==t.r&&void 0!==t.g&&void 0!==t.b){var a=void 0!==t.a?t.a:"1.0";i={r:t.r,g:t.g,b:t.b,a:a}}if(void 0===i)throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: "+Dy(t));this._setColor(i,e)}}},{key:"show",value:function(){void 0!==this.closeCallback&&(this.closeCallback(),this.closeCallback=void 0),this.applied=!1,this.frame.style.display="block",this._generateHueCircle()}},{key:"_hide",value:function(){var t=this;!0===(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&(this.previousColor=SA.extend({},this.color)),!0===this.applied&&this.updateCallback(this.initialColor),this.frame.style.display="none",Xy((function(){void 0!==t.closeCallback&&(t.closeCallback(),t.closeCallback=void 0)}),0)}},{key:"_save",value:function(){this.updateCallback(this.color),this.applied=!1,this._hide()}},{key:"_apply",value:function(){this.applied=!0,this.updateCallback(this.color),this._updatePicker(this.color)}},{key:"_loadLast",value:function(){void 0!==this.previousColor?this.setColor(this.previousColor,!1):alert("There is no last color to load...")}},{key:"_setColor",value:function(t){!0===(!(arguments.length>1&&void 0!==arguments[1])||arguments[1])&&(this.initialColor=SA.extend({},t)),this.color=t;var e=SA.RGBToHSV(t.r,t.g,t.b),i=2*Math.PI,n=this.r*e.s,r=this.centerCoordinates.x+n*Math.sin(i*e.h),o=this.centerCoordinates.y+n*Math.cos(i*e.h);this.colorPickerSelector.style.left=r-.5*this.colorPickerSelector.clientWidth+"px",this.colorPickerSelector.style.top=o-.5*this.colorPickerSelector.clientHeight+"px",this._updatePicker(t)}},{key:"_setOpacity",value:function(t){this.color.a=t/100,this._updatePicker(this.color)}},{key:"_setBrightness",value:function(t){var e=SA.RGBToHSV(this.color.r,this.color.g,this.color.b);e.v=t/100;var i=SA.HSVToRGB(e.h,e.s,e.v);i.a=this.color.a,this.color=i,this._updatePicker()}},{key:"_updatePicker",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.color,e=SA.RGBToHSV(t.r,t.g,t.b),i=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1)),i.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var n=this.colorPickerCanvas.clientWidth,r=this.colorPickerCanvas.clientHeight;i.clearRect(0,0,n,r),i.putImageData(this.hueCircle,0,0),i.fillStyle="rgba(0,0,0,"+(1-e.v)+")",i.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),sb(i).call(i),this.brightnessRange.value=100*e.v,this.opacityRange.value=100*t.a,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}},{key:"_setSize",value:function(){this.colorPickerCanvas.style.width="100%",this.colorPickerCanvas.style.height="100%",this.colorPickerCanvas.width=289*this.pixelRatio,this.colorPickerCanvas.height=289*this.pixelRatio}},{key:"_create",value:function(){var t,e,i,n;if(this.frame=document.createElement("div"),this.frame.className="vis-color-picker",this.colorPickerDiv=document.createElement("div"),this.colorPickerSelector=document.createElement("div"),this.colorPickerSelector.className="vis-selector",this.colorPickerDiv.appendChild(this.colorPickerSelector),this.colorPickerCanvas=document.createElement("canvas"),this.colorPickerDiv.appendChild(this.colorPickerCanvas),this.colorPickerCanvas.getContext){var r=this.colorPickerCanvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(r.webkitBackingStorePixelRatio||r.mozBackingStorePixelRatio||r.msBackingStorePixelRatio||r.oBackingStorePixelRatio||r.backingStorePixelRatio||1),this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var o=document.createElement("DIV");o.style.color="red",o.style.fontWeight="bold",o.style.padding="10px",o.innerHTML="Error: your browser does not support HTML canvas",this.colorPickerCanvas.appendChild(o)}this.colorPickerDiv.className="vis-color",this.opacityDiv=document.createElement("div"),this.opacityDiv.className="vis-opacity",this.brightnessDiv=document.createElement("div"),this.brightnessDiv.className="vis-brightness",this.arrowDiv=document.createElement("div"),this.arrowDiv.className="vis-arrow",this.opacityRange=document.createElement("input");try{this.opacityRange.type="range",this.opacityRange.min="0",this.opacityRange.max="100"}catch(t){}this.opacityRange.value="100",this.opacityRange.className="vis-range",this.brightnessRange=document.createElement("input");try{this.brightnessRange.type="range",this.brightnessRange.min="0",this.brightnessRange.max="100"}catch(t){}this.brightnessRange.value="100",this.brightnessRange.className="vis-range",this.opacityDiv.appendChild(this.opacityRange),this.brightnessDiv.appendChild(this.brightnessRange);var s=this;this.opacityRange.onchange=function(){s._setOpacity(this.value)},this.opacityRange.oninput=function(){s._setOpacity(this.value)},this.brightnessRange.onchange=function(){s._setBrightness(this.value)},this.brightnessRange.oninput=function(){s._setBrightness(this.value)},this.brightnessLabel=document.createElement("div"),this.brightnessLabel.className="vis-label vis-brightness",this.brightnessLabel.innerHTML="brightness:",this.opacityLabel=document.createElement("div"),this.opacityLabel.className="vis-label vis-opacity",this.opacityLabel.innerHTML="opacity:",this.newColorDiv=document.createElement("div"),this.newColorDiv.className="vis-new-color",this.newColorDiv.innerHTML="new",this.initialColorDiv=document.createElement("div"),this.initialColorDiv.className="vis-initial-color",this.initialColorDiv.innerHTML="initial",this.cancelButton=document.createElement("div"),this.cancelButton.className="vis-button vis-cancel",this.cancelButton.innerHTML="cancel",this.cancelButton.onclick=Uf(t=this._hide).call(t,this,!1),this.applyButton=document.createElement("div"),this.applyButton.className="vis-button vis-apply",this.applyButton.innerHTML="apply",this.applyButton.onclick=Uf(e=this._apply).call(e,this),this.saveButton=document.createElement("div"),this.saveButton.className="vis-button vis-save",this.saveButton.innerHTML="save",this.saveButton.onclick=Uf(i=this._save).call(i,this),this.loadButton=document.createElement("div"),this.loadButton.className="vis-button vis-load",this.loadButton.innerHTML="load last",this.loadButton.onclick=Uf(n=this._loadLast).call(n,this),this.frame.appendChild(this.colorPickerDiv),this.frame.appendChild(this.arrowDiv),this.frame.appendChild(this.brightnessLabel),this.frame.appendChild(this.brightnessDiv),this.frame.appendChild(this.opacityLabel),this.frame.appendChild(this.opacityDiv),this.frame.appendChild(this.newColorDiv),this.frame.appendChild(this.initialColorDiv),this.frame.appendChild(this.cancelButton),this.frame.appendChild(this.applyButton),this.frame.appendChild(this.saveButton),this.frame.appendChild(this.loadButton)}},{key:"_bindHammer",value:function(){var t=this;this.drag={},this.pinch={},this.hammer=new kL(this.colorPickerCanvas),this.hammer.get("pinch").set({enable:!0}),xL(this.hammer,(function(e){t._moveSelector(e)})),this.hammer.on("tap",(function(e){t._moveSelector(e)})),this.hammer.on("panstart",(function(e){t._moveSelector(e)})),this.hammer.on("panmove",(function(e){t._moveSelector(e)})),this.hammer.on("panend",(function(e){t._moveSelector(e)}))}},{key:"_generateHueCircle",value:function(){if(!1===this.generated){var t=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var e,i,n,r,o=this.colorPickerCanvas.clientWidth,s=this.colorPickerCanvas.clientHeight;t.clearRect(0,0,o,s),this.centerCoordinates={x:.5*o,y:.5*s},this.r=.49*o;var a,l=2*Math.PI/360,h=1/this.r;for(n=0;n<360;n++)for(r=0;r3&&void 0!==arguments[3]?arguments[3]:1;Sc(this,t),this.parent=e,this.changedOptions=[],this.container=i,this.allowCreation=!1,this.options={},this.initialized=!1,this.popupCounter=0,this.defaultOptions={enabled:!1,filter:!0,container:void 0,showButton:!0},SA.extend(this.options,this.defaultOptions),this.configureOptions=n,this.moduleOptions={},this.domElements=[],this.popupDiv={},this.popupLimit=5,this.popupHistory={},this.colorPicker=new RR(r),this.wrapper=void 0}return Wd(t,[{key:"setOptions",value:function(t){if(void 0!==t){this.popupHistory={},this._removePopup();var e=!0;if("string"==typeof t)this.options.filter=t;else if(tf(t))this.options.filter=t.join();else if("object"===Nd(t)){if(null==t)throw new TypeError("options cannot be null");void 0!==t.container&&(this.options.container=t.container),void 0!==ig(t)&&(this.options.filter=ig(t)),void 0!==t.showButton&&(this.options.showButton=t.showButton),void 0!==t.enabled&&(e=t.enabled)}else"boolean"==typeof t?(this.options.filter=!0,e=t):"function"==typeof t&&(this.options.filter=t,e=!0);!1===ig(this.options)&&(e=!1),this.options.enabled=e}this._clean()}},{key:"setModuleOptions",value:function(t){this.moduleOptions=t,!0===this.options.enabled&&(this._clean(),void 0!==this.options.container&&(this.container=this.options.container),this._create())}},{key:"_create",value:function(){this._clean(),this.changedOptions=[];var t=ig(this.options),e=0,i=!1;for(var n in this.configureOptions)this.configureOptions.hasOwnProperty(n)&&(this.allowCreation=!1,i=!1,"function"==typeof t?i=(i=t(n,[]))||this._handleObject(this.configureOptions[n],[n],!0):!0!==t&&-1===Qg(t).call(t,n)||(i=!0),!1!==i&&(this.allowCreation=!0,e>0&&this._makeItem([]),this._makeHeader(n),this._handleObject(this.configureOptions[n],[n])),e++);this._makeButton(),this._push()}},{key:"_push",value:function(){this.wrapper=document.createElement("div"),this.wrapper.className="vis-configuration-wrapper",this.container.appendChild(this.wrapper);for(var t=0;t1?i-1:0),r=1;r2&&void 0!==arguments[2]&&arguments[2],n=document.createElement("div");return n.className="vis-configuration vis-config-label vis-config-s"+e.length,n.innerHTML=!0===i?SA.xss(""+t+":"):SA.xss(t+":"),n}},{key:"_makeDropdown",value:function(t,e,i){var n=document.createElement("select");n.className="vis-configuration vis-config-select";var r=0;void 0!==e&&-1!==Qg(t).call(t,e)&&(r=Qg(t).call(t,e));for(var o=0;oo&&1!==o&&(a.max=Math.ceil(e*u),h=a.max,l="range increased"),a.value=e}else a.value=n;var c=document.createElement("input");c.className="vis-configuration vis-config-rangeinput",c.value=Number(a.value);var d=this;a.onchange=function(){c.value=this.value,d._update(Number(this.value),i)},a.oninput=function(){c.value=this.value};var p=this._makeLabel(i[i.length-1],i),f=this._makeItem(i,p,a,c);""!==l&&this.popupHistory[f]!==h&&(this.popupHistory[f]=h,this._setupPopup(l,f))}},{key:"_makeButton",value:function(){var t=this;if(!0===this.options.showButton){var e=document.createElement("div");e.className="vis-configuration vis-config-button",e.innerHTML="generate options",e.onclick=function(){t._printOptions()},e.onmouseover=function(){e.className="vis-configuration vis-config-button hover"},e.onmouseout=function(){e.className="vis-configuration vis-config-button"},this.optionsContainer=document.createElement("div"),this.optionsContainer.className="vis-configuration vis-config-option-container",this.domElements.push(this.optionsContainer),this.domElements.push(e)}}},{key:"_setupPopup",value:function(t,e){var i=this;if(!0===this.initialized&&!0===this.allowCreation&&this.popupCounter1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=!1,r=ig(this.options),o=!1;for(var s in t)if(t.hasOwnProperty(s)){n=!0;var a=t[s],l=SA.copyAndExtendArray(e,s);if("function"==typeof r&&!1===(n=r(s,e))&&!tf(a)&&"string"!=typeof a&&"boolean"!=typeof a&&a instanceof Object&&(this.allowCreation=!1,n=this._handleObject(a,l,!0),this.allowCreation=!1===i),!1!==n){o=!0;var h=this._getValue(l);if(tf(a))this._handleArray(a,h,l);else if("string"==typeof a)this._makeTextInput(a,h,l);else if("boolean"==typeof a)this._makeCheckbox(a,h,l);else if(a instanceof Object){var u=!0;if(-1!==Qg(e).call(e,"physics")&&this.moduleOptions.physics.solver!==s&&(u=!1),!0===u)if(void 0!==a.enabled){var c=SA.copyAndExtendArray(l,"enabled"),d=this._getValue(c);if(!0===d){var p=this._makeLabel(s,l,!0);this._makeItem(l,p),o=this._handleObject(a,l)||o}else this._makeCheckbox(a,d,l)}else{var f=this._makeLabel(s,l,!0);this._makeItem(l,f),o=this._handleObject(a,l)||o}}else console.error("dont know how to handle",a,s,l)}}return o}},{key:"_handleArray",value:function(t,e,i){"string"==typeof t[0]&&"color"===t[0]?(this._makeColorField(t,e,i),t[1]!==e&&this.changedOptions.push({path:i,value:e})):"string"==typeof t[0]?(this._makeDropdown(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:e})):"number"==typeof t[0]&&(this._makeRange(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:Number(e)}))}},{key:"_update",value:function(t,e){var i=this._constructOptions(t,e);this.parent.body&&this.parent.body.emitter&&this.parent.body.emitter.emit&&this.parent.body.emitter.emit("configChange",i),this.initialized=!0,this.parent.setOptions(i)}},{key:"_constructOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=i;t="false"!==(t="true"===t||t)&&t;for(var r=0;rvar options = "+Dy(t,null,2)+""}},{key:"getOptions",value:function(){for(var t={},e=0;eo)&&(o=i)})),null!==r&&null!==o){var s=this,a=this.itemSet.items[i[0]],l=-1*this._getScrollTop(),h=null,u=function(){var t=BR(s,a);t.shouldScroll&&t.itemTop!=h.itemTop&&(s._setScrollTop(-t.scrollOffset),s._redraw())},c=!e||void 0===e.zoom||e.zoom,d=(r+o)/2,p=c?1.1*(o-r):Math.max(this.range.end-this.range.start,1.1*(o-r)),f=!e||void 0===e.animation||e.animation;f||(h={shouldScroll:!1,scrollOffset:-1,itemTop:-1}),this.range.setRange(d-p/2,d+p/2,{animation:f},(function(){u(),Xy(u,100)}),(function(t,e,i){var n=BR(s,a);if(!1!==n&&(h||(h=n),h.itemTop!=n.itemTop||h.shouldScroll)){h.itemTop!=n.itemTop&&n.shouldScroll&&(h=n,l=-1*s._getScrollTop());var r=l,o=h.scrollOffset,u=i?o:r+(o-r)*t;s._setScrollTop(-u),e||s._redraw()}}))}}}},{key:"fit",value:function(t,e){var i,n=!t||void 0===t.animation||t.animation;1===this.itemsData.length&&void 0===this.itemsData.get()[0].end?(i=this.getDataRange(),this.moveTo(i.min.valueOf(),{animation:n},e)):(i=this.getItemRange(),this.range.setRange(i.min,i.max,{animation:n},e))}},{key:"getItemRange",value:function(){var t=this,e=this.getDataRange(),i=null!==e.min?e.min.valueOf():null,n=null!==e.max?e.max.valueOf():null,r=null,o=null;if(null!=i&&null!=n){var s=n-i;s<=0&&(s=10);var a=s/this.props.center.width,l={},h=0;if(am(SA).call(SA,this.itemSet.items,(function(t,e){if(t.groupShowing){l[e]=t.redraw(!0),h=l[e].length}})),h>0)for(var u=function(t){am(SA).call(SA,l,(function(e){e[t]()}))},c=0;cn&&(n=l,o=e)})),r&&o){var d=r.getWidthLeft()+10,p=o.getWidthRight()+10,f=this.props.center.width-d-p;f>0&&(this.options.rtl?(i=HR(r)-p*s/f,n=zR(o)+d*s/f):(i=HR(r)-d*s/f,n=zR(o)+p*s/f))}}return{min:null!=i?new Date(i):null,max:null!=n?new Date(n):null}}},{key:"getDataRange",value:function(){var t,e=null,i=null;this.itemsData&&am(t=this.itemsData).call(t,(function(t){var n=SA.convert(t.start,"Date").valueOf(),r=SA.convert(null!=t.end?t.end:t.start,"Date").valueOf();(null===e||ni)&&(i=r)}));return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}}},{key:"getEventProperties",value:function(t){var e=t.center?t.center.x:t.clientX,i=t.center?t.center.y:t.clientY,n=this.dom.centerContainer.getBoundingClientRect(),r=this.options.rtl?n.right-e:e-n.left,o=i-n.top,s=this.itemSet.itemFromTarget(t),a=this.itemSet.groupFromTarget(t),l=XL.customTimeFromTarget(t),h=this.itemSet.options.snap||null,u=this.body.util.getScale(),c=this.body.util.getStep(),d=this._toTime(r),p=h?h(d,u,c):d,f=SA.getTarget(t),m=null;return null!=s?m="item":null!=l?m="custom-time":SA.hasParent(f,this.timeAxis.dom.foreground)||this.timeAxis2&&SA.hasParent(f,this.timeAxis2.dom.foreground)?m="axis":SA.hasParent(f,this.itemSet.dom.labelSet)?m="group-label":SA.hasParent(f,this.currentTime.bar)?m="current-time":SA.hasParent(f,this.dom.center)&&(m="background"),{event:t,item:s?s.id:null,isCluster:!!s&&!!s.isCluster,items:s?s.items||[]:null,group:a?a.groupId:null,customTime:l?l.options.id:null,what:m,pageX:t.srcEvent?t.srcEvent.pageX:t.pageX,pageY:t.srcEvent?t.srcEvent.pageY:t.pageY,x:r,y:o,time:d,snappedTime:p}}},{key:"toggleRollingMode",value:function(){this.range.rolling?this.range.stopRolling():(null==this.options.rollingMode&&this.setOptions(this.options),this.range.startRolling())}},{key:"_redraw",value:function(){qL.prototype._redraw.call(this)}},{key:"_onFit",value:function(t){var e=t.start,i=t.end,n=t.animation;i?this.range.setRange(e,i,{animation:n}):this.moveTo(e.valueOf(),{animation:n})}}]),i}(qL);function HR(t){return SA.convert(t.data.start,"Date").valueOf()}function zR(t){var e=null!=t.data.end?t.data.end:t.data.start;return SA.convert(e,"Date").valueOf()}function BR(t,e){if(!e.parent)return!1;var i=t.options.rtl?t.props.rightContainer.height:t.props.leftContainer.height,n=t.props.center.height,r=e.parent,o=r.top,s=!0,a=t.timeAxis.options.orientation.axis,l=function(){return"bottom"==a?r.height-e.top-e.height:e.top},h=-1*t._getScrollTop(),u=o+l(),c=e.height;return uh+i?o+=l()+c-i+t.itemSet.options.margin.item.vertical:s=!1,{shouldScroll:s,scrollOffset:o=Math.min(o,n-i),itemTop:u}}var GR=function(){function t(e,i,n,r,o,s){var a=arguments.length>6&&void 0!==arguments[6]&&arguments[6],l=arguments.length>7&&void 0!==arguments[7]&&arguments[7];if(Sc(this,t),this.majorSteps=[1,2,5,10],this.minorSteps=[.25,.5,1,2],this.customLines=null,this.containerHeight=o,this.majorCharHeight=s,this._start=e,this._end=i,this.scale=1,this.minorStepIdx=-1,this.magnitudefactor=1,this.determineScale(),this.zeroAlign=a,this.autoScaleStart=n,this.autoScaleEnd=r,this.formattingFunction=l,n||r){var h=this,u=function(t){var e=t-t%(h.magnitudefactor*h.minorSteps[h.minorStepIdx]);return t%(h.magnitudefactor*h.minorSteps[h.minorStepIdx])>h.magnitudefactor*h.minorSteps[h.minorStepIdx]*.5?e+h.magnitudefactor*h.minorSteps[h.minorStepIdx]:e};n&&(this._start-=2*this.magnitudefactor*this.minorSteps[this.minorStepIdx],this._start=u(this._start)),r&&(this._end+=this.magnitudefactor*this.minorSteps[this.minorStepIdx],this._end=u(this._end)),this.determineScale()}}return Wd(t,[{key:"setCharHeight",value:function(t){this.majorCharHeight=t}},{key:"setHeight",value:function(t){this.containerHeight=t}},{key:"determineScale",value:function(){var t=this._end-this._start;this.scale=this.containerHeight/t;var e=this.majorCharHeight/this.scale,i=t>0?Math.round(Math.log(t)/Math.LN10):0;this.minorStepIdx=-1,this.magnitudefactor=Math.pow(10,i);var n=0;i<0&&(n=i);for(var r=!1,o=n;Math.abs(o)<=Math.abs(i);o++){this.magnitudefactor=Math.pow(10,o);for(var s=0;s=e){r=!0,this.minorStepIdx=s;break}}if(!0===r)break}}},{key:"is_major",value:function(t){return t%(this.magnitudefactor*this.majorSteps[this.minorStepIdx])==0}},{key:"getStep",value:function(){return this.magnitudefactor*this.minorSteps[this.minorStepIdx]}},{key:"getFirstMajor",value:function(){var t=this.magnitudefactor*this.majorSteps[this.minorStepIdx];return this.convertValue(this._start+(t-this._start%t)%t)}},{key:"formatValue",value:function(t){var e=t.toPrecision(5);return"function"==typeof this.formattingFunction&&(e=this.formattingFunction(t)),"number"==typeof e?"".concat(e):"string"==typeof e?e:t.toPrecision(5)}},{key:"getLines",value:function(){for(var t=[],e=this.getStep(),i=(e-this._start%e)%e,n=this._start+i;this._end-n>1e-5;n+=e)n!=this._start&&t.push({major:this.is_major(n),y:this.convertValue(n),val:this.formatValue(n)});return t}},{key:"followScale",value:function(t){var e=this.minorStepIdx,i=this._start,n=this._end,r=this,o=function(){r.magnitudefactor*=2},s=function(){r.magnitudefactor/=2};t.minorStepIdx<=1&&this.minorStepIdx<=1||t.minorStepIdx>1&&this.minorStepIdx>1||(t.minorStepIdxn+1e-5)s(),h=!1;else{if(!this.autoScaleStart&&this._start=0)){s(),h=!1;continue}console.warn("Can't adhere to given 'min' range, due to zeroalign")}this.autoScaleStart&&this.autoScaleEnd&&c=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function VR(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i=0&&t._redrawLabel(n-2,e.val,i,"vis-y-axis vis-major",t.props.majorCharHeight),!0===t.master&&(r?t._redrawLine(n,i,"vis-grid vis-horizontal vis-major",t.options.majorLinesOffset,t.props.majorLineWidth):t._redrawLine(n,i,"vis-grid vis-horizontal vis-minor",t.options.minorLinesOffset,t.props.minorLineWidth))}));var a=0;void 0!==this.options[i].title&&void 0!==this.options[i].title.text&&(a=this.props.titleCharHeight);var l=!0===this.options.icons?Math.max(this.options.iconWidth,a)+this.options.labelOffsetX+15:a+this.options.labelOffsetX+15;return this.maxLabelSize>this.width-l&&!0===this.options.visible?(this.width=this.maxLabelSize+l,this.options.width="".concat(this.width,"px"),kk(this.DOMelements.lines),kk(this.DOMelements.labels),this.redraw(),e=!0):this.maxLabelSizethis.minWidth?(this.width=Math.max(this.minWidth,this.maxLabelSize+l),this.options.width="".concat(this.width,"px"),kk(this.DOMelements.lines),kk(this.DOMelements.labels),this.redraw(),e=!0):(kk(this.DOMelements.lines),kk(this.DOMelements.labels),e=!1),e}},{key:"convertValue",value:function(t){return this.scale.convertValue(t)}},{key:"screenToValue",value:function(t){return this.scale.screenToValue(t)}},{key:"_redrawLabel",value:function(t,e,i,n,r){var o=Sk("div",this.DOMelements.labels,this.dom.frame);o.className=n,o.innerHTML=SA.xss(e),"left"===i?(o.style.left="-".concat(this.options.labelOffsetX,"px"),o.style.textAlign="right"):(o.style.right="-".concat(this.options.labelOffsetX,"px"),o.style.textAlign="left"),o.style.top="".concat(t-.5*r+this.options.labelOffsetY,"px"),e+="";var s=Math.max(this.props.majorCharWidth,this.props.minorCharWidth);this.maxLabelSize0&&(i=Math.min(i,Math.abs(e[n-1].screen_x-e[n].screen_x))),0===i&&(void 0===t[e[n].screen_x]&&(t[e[n].screen_x]={amount:0,resolved:0,accumulatedPositive:0,accumulatedNegative:0}),t[e[n].screen_x].amount+=1)},ZR._getSafeDrawData=function(t,e,i){var n,r;return t0?(n=t0){LE(t).call(t,(function(t,e){return t.screen_x===e.screen_x?t.groupIde[o].screen_y?e[o].screen_y:n,r=rt[s].accumulatedNegative?t[s].accumulatedNegative:n)>t[s].accumulatedPositive?t[s].accumulatedPositive:n,r=(r=r0){return 1==e.options.interpolation.enabled?KR._catmullRom(t,e):KR._linear(t)}},KR.drawIcon=function(t,e,i,n,r,o){var s,a,l=.5*r,h=Dk("rect",o.svgElements,o.svg);(h.setAttributeNS(null,"x",e),h.setAttributeNS(null,"y",i-l),h.setAttributeNS(null,"width",n),h.setAttributeNS(null,"height",2*l),h.setAttributeNS(null,"class","vis-outline"),(s=Dk("path",o.svgElements,o.svg)).setAttributeNS(null,"class",t.className),void 0!==t.style&&s.setAttributeNS(null,"style",t.style),s.setAttributeNS(null,"d","M"+e+","+i+" L"+(e+n)+","+i),1==t.options.shaded.enabled&&(a=Dk("path",o.svgElements,o.svg),"top"==t.options.shaded.orientation?a.setAttributeNS(null,"d","M"+e+", "+(i-l)+"L"+e+","+i+" L"+(e+n)+","+i+" L"+(e+n)+","+(i-l)):a.setAttributeNS(null,"d","M"+e+","+i+" L"+e+","+(i+l)+" L"+(e+n)+","+(i+l)+"L"+(e+n)+","+i),a.setAttributeNS(null,"class",t.className+" vis-icon-fill"),void 0!==t.options.shaded.style&&""!==t.options.shaded.style&&a.setAttributeNS(null,"style",t.options.shaded.style)),1==t.options.drawPoints.enabled)&&Ck(e+.5*n,i,{style:t.options.drawPoints.style,styles:t.options.drawPoints.styles,size:t.options.drawPoints.size,className:t.className},o.svgElements,o.svg)},KR.drawShading=function(t,e,i,n){if(1==e.options.shaded.enabled){var r,o=Number(n.svg.style.height.replace("px","")),s=Dk("path",n.svgElements,n.svg),a="L";1==e.options.interpolation.enabled&&(a="C");var l=0;l="top"==e.options.shaded.orientation?0:"bottom"==e.options.shaded.orientation?o:Math.min(Math.max(0,e.zeroPosition),o),r="group"==e.options.shaded.orientation&&null!=i&&null!=i?"M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,a,!1)+" L"+i[i.length-1][0]+","+i[i.length-1][1]+" "+this.serializePath(i,a,!0)+i[0][0]+","+i[0][1]+" Z":"M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,a,!1)+" V"+l+" H"+t[0][0]+" Z",s.setAttributeNS(null,"class",e.className+" vis-fill"),void 0!==e.options.shaded.style&&s.setAttributeNS(null,"style",e.options.shaded.style),s.setAttributeNS(null,"d",r)}},KR.draw=function(t,e,i){if(null!=t&&null!=t){var n=Dk("path",i.svgElements,i.svg);n.setAttributeNS(null,"class",e.className),void 0!==e.style&&n.setAttributeNS(null,"style",e.style);var r="L";1==e.options.interpolation.enabled&&(r="C"),n.setAttributeNS(null,"d","M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,r,!1))}},KR.serializePath=function(t,e,i){if(t.length<2)return"";var n,r=e;if(i)for(n=t.length-2;n>0;n--)r+=t[n][0]+","+t[n][1]+" ";else for(n=1;n0&&(f=1/f),(m=3*v*(v+g))>0&&(m=1/m),a={screen_x:(-b*n.screen_x+d*r.screen_x+_*o.screen_x)*f,screen_y:(-b*n.screen_y+d*r.screen_y+_*o.screen_y)*f},l={screen_x:(y*r.screen_x+p*o.screen_x-b*s.screen_x)*m,screen_y:(y*r.screen_y+p*o.screen_y-b*s.screen_y)*m},0==a.screen_x&&0==a.screen_y&&(a=r),0==l.screen_x&&0==l.screen_y&&(l=o),k.push([a.screen_x,a.screen_y]),k.push([l.screen_x,l.screen_y]),k.push([o.screen_x,o.screen_y]);return k},KR._linear=function(t){for(var e=[],i=0;ie.x?1:-1}))):this.itemsData=[]},JR.prototype.getItems=function(){return this.itemsData},JR.prototype.setZeroPosition=function(t){this.zeroPosition=t},JR.prototype.setOptions=function(t){if(void 0!==t){SA.selectiveDeepExtend(["sampling","style","sort","yAxisOrientation","barChart","zIndex","excludeFromStacking","excludeFromLegend"],this.options,t),"function"==typeof t.drawPoints&&(t.drawPoints={onRender:t.drawPoints}),SA.mergeOptions(this.options,t,"interpolation"),SA.mergeOptions(this.options,t,"drawPoints"),SA.mergeOptions(this.options,t,"shaded"),t.interpolation&&"object"==Nd(t.interpolation)&&t.interpolation.parametrization&&("uniform"==t.interpolation.parametrization?this.options.interpolation.alpha=0:"chordal"==t.interpolation.parametrization?this.options.interpolation.alpha=1:(this.options.interpolation.parametrization="centripetal",this.options.interpolation.alpha=.5))}},JR.prototype.update=function(t){this.group=t,this.content=t.content||"graph",this.className=t.className||this.className||"vis-graph-group"+this.groupsUsingDefaultStyles[0]%10,this.visible=void 0===t.visible||t.visible,this.style=t.style,this.setOptions(t.options)},JR.prototype.getLegend=function(t,e,i,n,r){null!=i&&null!=i||(i={svg:document.createElementNS("http://www.w3.org/2000/svg","svg"),svgElements:{},options:this.options,groups:[this]});switch(null!=n&&null!=n||(n=0),null!=r&&null!=r||(r=.5*e),this.options.style){case"line":KR.drawIcon(this,n,r,t,e,i);break;case"points":case"point":qR.drawIcon(this,n,r,t,e,i);break;case"bar":ZR.drawIcon(this,n,r,t,e,i)}return{icon:i.svg,label:this.content,orientation:this.options.yAxisOrientation}},JR.prototype.getYRange=function(t){for(var e=t[0].y,i=t[0].y,n=0;nt[n].y?t[n].y:e,i=i");this.dom.textArea.innerHTML=SA.xss(o),this.dom.textArea.style.lineHeight=.75*this.options.iconSize+this.options.iconSpacing+"px"}},QR.prototype.drawLegendIcons=function(){if(this.dom.frame.parentNode){var t=gf(this.groups);LE(t).call(t,(function(t,e){return t0){var s={};for(this._getRelevantData(o,s,n,r),this._applySampling(o,s),e=0;e0)switch(t.options.style){case"line":l.hasOwnProperty(o[e])||(l[o[e]]=KR.calcPath(s[o[e]],t)),KR.draw(l[o[e]],t,this.framework);case"point":case"points":"point"!=t.options.style&&"points"!=t.options.style&&1!=t.options.drawPoints.enabled||qR.draw(s[o[e]],t,this.framework)}}}return kk(this.svgElements),!1},eF.prototype._stack=function(t,e){var i,n,r,o,s;i=0;for(var a=0;at[a].x){s=e[l],o=0==l?s:e[l-1],i=l;break}}void 0===s&&(o=e[e.length-1],s=e[e.length-1]),n=s.x-o.x,r=s.y-o.y,t[a].y=0==n?t[a].orginalY+s.y:t[a].orginalY+r/n*(t[a].x-o.x)+o.y}},eF.prototype._getRelevantData=function(t,e,i,n){var r,o,s,a;if(t.length>0)for(o=0;o0)for(var i=0;i0){var r,o=n.length,s=o/(this.body.util.toGlobalScreen(n[n.length-1].x)-this.body.util.toGlobalScreen(n[0].x));r=Math.min(Math.ceil(.2*o),Math.max(1,Math.round(s)));for(var a=new Array(o),l=0;l0){for(o=0;o0&&(r=this.groups[t[o]],!0===s.stack&&"bar"===s.style?"left"===s.yAxisOrientation?a=Up(a).call(a,n):l=Up(l).call(l,n):i[t[o]]=r.getYRange(n,t[o]));ZR.getStackedYRange(a,i,t,"__barStackLeft","left"),ZR.getStackedYRange(l,i,t,"__barStackRight","right")}},eF.prototype._updateYAxis=function(t,e){var i,n,r=!1,o=!1,s=!1,a=1e9,l=1e9,h=-1e9,u=-1e9;if(t.length>0){for(var c=0;ci?i:a,h=hi?i:l,u=uo?o:t,e=null==e||e0&&h.push(u.screenToValue(r)),!c.hidden&&this.itemsData.length>0&&h.push(c.screenToValue(r)),{event:t,customTime:s?s.options.id:null,what:l,pageX:t.srcEvent?t.srcEvent.pageX:t.pageX,pageY:t.srcEvent?t.srcEvent.pageY:t.pageY,x:n,y:r,time:o,value:h}},uF.prototype._createConfigurator=function(){return new FR(this,this.dom.container,hF)};var cF=Mk();hI.locale(cF);var dF={Core:qL,DateUtil:pL,Range:mL,stack:NN,TimeStep:DL,components:{items:{Item:BN,BackgroundItem:ZN,BoxItem:WN,ClusterItem:cR,PointItem:UN,RangeItem:qN},BackgroundGroup:YN,Component:HA,CurrentTime:ZL,CustomTime:XL,DataAxis:XR,DataScale:GR,GraphGroup:JR,Group:FN,ItemSet:wR,Legend:QR,LineGraph:eF,TimeAxis:TL}};t.DOMutil=Ok,t.DataSet=sI,t.DataView=aI,t.Graph2d=uF,t.Hammer=kL,t.Queue=nI,t.Timeline=YR,t.keycharm=OL,t.moment=hI,t.timeline=dF,t.util=_k})); + * Licensed under the MIT license */ +function Zv(){return Zv=Object.assign||function(t){for(var e=1;e-1}var jg=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===hg&&(t=this.compute()),lg&&this.manager.element.style&&mg[t]&&(this.manager.element.style[ag]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return Ng(this.manager.recognizers,(function(e){Rg(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(Fg(t,cg))return cg;var e=Fg(t,pg),i=Fg(t,fg);return e&&i?cg:e||i?e?pg:fg:Fg(t,dg)?dg:ug}(t.join(" "))},e.preventDefaults=function(t){var e=t.srcEvent,i=t.offsetDirection;if(this.manager.session.prevented)e.preventDefault();else{var n=this.actions,r=Fg(n,cg)&&!mg[cg],o=Fg(n,fg)&&!mg[fg],s=Fg(n,pg)&&!mg[pg];if(r){var a=1===t.pointers.length,l=t.distance<2,h=t.deltaTime<250;if(a&&l&&h)return}if(!s||!o)return r||o&&i&Eg||s&&i&Pg?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function Yg(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function Hg(t){var e=t.length;if(1===e)return{x:ng(t[0].clientX),y:ng(t[0].clientY)};for(var i=0,n=0,r=0;r=rg(e)?t<0?Cg:Tg:e<0?Mg:Og}function Vg(t,e,i){return{x:e/t||0,y:i/t||0}}function Ug(t,e){var i=t.session,n=e.pointers,r=n.length;i.firstInput||(i.firstInput=zg(e)),r>1&&!i.firstMultiple?i.firstMultiple=zg(e):1===r&&(i.firstMultiple=!1);var o=i.firstInput,s=i.firstMultiple,a=s?s.center:o.center,l=e.center=Hg(n);e.timeStamp=og(),e.deltaTime=e.timeStamp-o.timeStamp,e.angle=Gg(a,l),e.distance=Bg(a,l),function(t,e){var i=e.center,n=t.offsetDelta||{},r=t.prevDelta||{},o=t.prevInput||{};e.eventType!==kg&&o.eventType!==xg||(r=t.prevDelta={x:o.deltaX||0,y:o.deltaY||0},n=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=r.x+(i.x-n.x),e.deltaY=r.y+(i.y-n.y)}(i,e),e.offsetDirection=Wg(e.deltaX,e.deltaY);var h,u,d=Vg(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=d.x,e.overallVelocityY=d.y,e.overallVelocity=rg(d.x)>rg(d.y)?d.x:d.y,e.scale=s?(h=s.pointers,Bg((u=n)[0],u[1],Lg)/Bg(h[0],h[1],Lg)):1,e.rotation=s?function(t,e){return Gg(e[1],e[0],Lg)+Gg(t[1],t[0],Lg)}(s.pointers,n):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,n,r,o,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==Dg&&(a>wg||void 0===s.velocity)){var l=e.deltaX-s.deltaX,h=e.deltaY-s.deltaY,u=Vg(a,l,h);n=u.x,r=u.y,i=rg(u.x)>rg(u.y)?u.x:u.y,o=Wg(l,h),t.lastInterval=e}else i=s.velocity,n=s.velocityX,r=s.velocityY,o=s.direction;e.velocity=i,e.velocityX=n,e.velocityY=r,e.direction=o}(i,e);var c,p=t.element,f=e.srcEvent;Yg(c=f.composedPath?f.composedPath()[0]:f.path?f.path[0]:f.target,p)&&(p=c),e.target=p}function Xg(t,e,i){var n=i.pointers.length,r=i.changedPointers.length,o=e&kg&&n-r==0,s=e&(xg|Dg)&&n-r==0;i.isFirst=!!o,i.isFinal=!!s,o&&(t.session={}),i.eventType=e,Ug(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function qg(t){return t.trim().split(/\s+/g)}function $g(t,e,i){Ng(qg(e),(function(e){t.addEventListener(e,i,!1)}))}function Zg(t,e,i){Ng(qg(e),(function(e){t.removeEventListener(e,i,!1)}))}function Kg(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var Jg=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){Rg(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&$g(this.element,this.evEl,this.domHandler),this.evTarget&&$g(this.target,this.evTarget,this.domHandler),this.evWin&&$g(Kg(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&Zg(this.element,this.evEl,this.domHandler),this.evTarget&&Zg(this.target,this.evTarget,this.domHandler),this.evWin&&Zg(Kg(this.element),this.evWin,this.domHandler)},t}();function Qg(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var n=0;ni[e]})):n.sort()),n}var ay={touchstart:kg,touchmove:2,touchend:xg,touchcancel:Dg},ly=function(t){function e(){var i;return e.prototype.evTarget="touchstart touchmove touchend touchcancel",(i=t.apply(this,arguments)||this).targetIds={},i}return Kv(e,t),e.prototype.handler=function(t){var e=ay[t.type],i=hy.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:bg,srcEvent:t})},e}(Jg);function hy(t,e){var i,n,r=oy(t.touches),o=this.targetIds;if(e&(2|kg)&&1===r.length)return o[r[0].identifier]=!0,[r,r];var s=oy(t.changedTouches),a=[],l=this.target;if(n=r.filter((function(t){return Yg(t.target,l)})),e===kg)for(i=0;i-1&&n.splice(t,1)}),cy)}}function fy(t,e){t&kg?(this.primaryTouch=e.changedPointers[0].identifier,py.call(this,e)):t&(xg|Dg)&&py.call(this,e)}function my(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,n=0;n-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function n(i){e.manager.emit(i,t)}i<8&&n(e.options.event+wy(i)),n(e.options.event),t.additionalEvent&&n(t.additionalEvent),i>=8&&n(e.options.event+wy(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=yy},e.canEmit=function(){for(var t=0;te.threshold&&r&e.direction},i.attrTest=function(t){return Dy.prototype.attrTest.call(this,t)&&(2&this.state||!(2&this.state)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=Sy(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}(Dy),Ty=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Zv({event:"swipe",threshold:10,velocity:.3,direction:Eg|Pg,pointers:1},e))||this}Kv(e,t);var i=e.prototype;return i.getTouchAction=function(){return Cy.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,n=this.options.direction;return n&(Eg|Pg)?i=e.overallVelocity:n&Eg?i=e.overallVelocityX:n&Pg&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&n&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&rg(i)>this.options.velocity&&e.eventType&xg},i.emit=function(t){var e=Sy(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}(Dy),My=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Zv({event:"pinch",threshold:0,pointers:2},e))||this}Kv(e,t);var i=e.prototype;return i.getTouchAction=function(){return[cg]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||2&this.state)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}(Dy),Oy=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Zv({event:"rotate",threshold:0,pointers:2},e))||this}Kv(e,t);var i=e.prototype;return i.getTouchAction=function(){return[cg]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||2&this.state)},e}(Dy),Ey=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,Zv({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}Kv(e,t);var i=e.prototype;return i.getTouchAction=function(){return[ug]},i.process=function(t){var e=this,i=this.options,n=t.pointers.length===i.pointers,r=t.distancei.time;if(this._input=t,!r||!n||t.eventType&(xg|Dg)&&!o)this.reset();else if(t.eventType&kg)this.reset(),this._timer=setTimeout((function(){e.state=8,e.tryEmit()}),i.time);else if(t.eventType&xg)return 8;return yy},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){8===this.state&&(t&&t.eventType&xg?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=og(),this.manager.emit(this.options.event,this._input)))},e}(ky),Py={domEvents:!1,touchAction:hg,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},Ay=[[Oy,{enable:!1}],[My,{enable:!1},["rotate"]],[Ty,{direction:Eg}],[Cy,{direction:Eg},["swipe"]],[xy],[xy,{event:"doubletap",taps:2},["tap"]],[Ey]];function Iy(t,e){var i,n=t.element;n.style&&(Ng(t.options.cssProps,(function(r,o){i=sg(n.style,o),e?(t.oldCssProps[i]=n.style[i],n.style[i]=r):n.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var Ly=function(){function t(t,e){var i,n=this;this.options=tg({},Py,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||(gg?ry:yg?ly:vg?vy:dy))(i,Xg),this.touchAction=new jg(this,this.options.touchAction),Iy(this,!0),Ng(this.options.recognizers,(function(t){var e=n.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return tg(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var n=this.recognizers,r=e.curRecognizer;(!r||r&&8&r.state)&&(e.curRecognizer=null,r=null);for(var o=0;o\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",r=window.console&&(window.console.warn||window.console.log);return r&&r.call(window.console,n,i),t.apply(this,arguments)}}var Yy=jy((function(t,e,i){for(var n=Object.keys(e),r=0;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function Uy(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?i-1:0),r=1;r2)return Zy.apply(void 0,Yc(n=[$y(e[0],e[1])]).call(n,Ac(Hc(e).call(e,2))));var r=e[0],o=e[1];if(r instanceof Date&&o instanceof Date)return r.setTime(o.getTime()),r;var s,a=Vy(Xc(o));try{for(a.s();!(s=a.n()).done;){var l=s.value;Object.prototype.propertyIsEnumerable.call(o,l)&&(o[l]===Xy?delete r[l]:null===r[l]||null===o[l]||"object"!==Nd(r[l])||"object"!==Nd(o[l])||qc(r[l])||qc(o[l])?r[l]=Ky(o[l]):r[l]=Zy(r[l],o[l]))}}catch(t){a.e(t)}finally{a.f()}return r}function Ky(t){return qc(t)?ep(t).call(t,(function(t){return Ky(t)})):"object"===Nd(t)&&null!==t?t instanceof Date?new Date(t.getTime()):Zy({},t):t}function Jy(t){for(var e=0,i=rp(t);e2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r)||!0===i)if("object"===Nd(e[r])&&null!==e[r]&&lm(e[r])===Object.prototype)void 0===t[r]?t[r]=db({},e[r],i):"object"===Nd(t[r])&&null!==t[r]&&lm(t[r])===Object.prototype?db(t[r],e[r],i):hb(t,e,r,n);else if(qc(e[r])){var o;t[r]=Hc(o=e[r]).call(o)}else hb(t,e,r,n);return t}function cb(t){var e=Nd(t);return"object"===e?null===t?"null":t instanceof Boolean?"Boolean":t instanceof Number?"Number":t instanceof String?"String":qc(t)?"Array":t instanceof Date?"Date":"Object":"number"===e?"Number":"boolean"===e?"Boolean":"string"===e?"String":void 0===e?"undefined":e}function pb(t,e){var i;return Yc(i=[]).call(i,Ac(t),[e])}function fb(t){return Hc(t).call(t)}var mb=Mm;var vb={asBoolean:function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},asNumber:function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},asString:function(t,e){return"function"==typeof t&&(t=t()),null!=t?String(t):e||null},asSize:function(t,e){return"function"==typeof t&&(t=t()),ab(t)?t:sb(t)?t+"px":e||null},asElement:function(t,e){return"function"==typeof t&&(t=t()),t||e||null}};function gb(t){var e;switch(t.length){case 3:case 4:return(e=nb.exec(t))?{r:Zm(e[1]+e[1],16),g:Zm(e[2]+e[2],16),b:Zm(e[3]+e[3],16)}:null;case 6:case 7:return(e=ib.exec(t))?{r:Zm(e[1],16),g:Zm(e[2],16),b:Zm(e[3],16)}:null;default:return null}}function yb(t,e,i){var n;return"#"+Hc(n=((1<<24)+(t<<16)+(e<<8)+i).toString(16)).call(n,1)}function bb(t,e,i){t/=255,e/=255,i/=255;var n=Math.min(t,Math.min(e,i)),r=Math.max(t,Math.max(e,i));return n===r?{h:0,s:0,v:n}:{h:60*((t===n?3:i===n?1:5)-(t===n?e-i:i===n?t-e:i-t)/(r-n))/360,s:(r-n)/r,v:r}}function _b(t){var e=document.createElement("div"),i={};e.style.cssText=t;for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:1;Ma(this,t),this.pixelRatio=e,this.generated=!1,this.centerCoordinates={x:144.5,y:144.5},this.r=289*.49,this.color={r:255,g:255,b:255,a:1},this.hueCircle=void 0,this.initialColor={r:255,g:255,b:255,a:1},this.previousColor=void 0,this.applied=!1,this.updateCallback=function(){},this.closeCallback=function(){},this._create()}return Yd(t,[{key:"insertTo",value:function(t){void 0!==this.hammer&&(this.hammer.destroy(),this.hammer=void 0),this.container=t,this.container.appendChild(this.frame),this._bindHammer(),this._setSize()}},{key:"setUpdateCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker update callback is not a function.");this.updateCallback=t}},{key:"setCloseCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker closing callback is not a function.");this.closeCallback=t}},{key:"_isColorString",value:function(t){if("string"==typeof t)return Mb[t]}},{key:"setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if("none"!==t){var i,n=this._isColorString(t);if(void 0!==n&&(t=n),!0===ab(t)){if(!0===Sb(t)){var r=t.substr(4).substr(0,t.length-5).split(",");i={r:r[0],g:r[1],b:r[2],a:1}}else if(!0===Cb(t)){var o=t.substr(5).substr(0,t.length-6).split(",");i={r:o[0],g:o[1],b:o[2],a:o[3]}}else if(!0===Db(t)){var s=gb(t);i={r:s.r,g:s.g,b:s.b,a:1}}}else if(t instanceof Object&&void 0!==t.r&&void 0!==t.g&&void 0!==t.b){var a=void 0!==t.a?t.a:"1.0";i={r:t.r,g:t.g,b:t.b,a:a}}if(void 0===i)throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: "+vv(t));this._setColor(i,e)}}},{key:"show",value:function(){void 0!==this.closeCallback&&(this.closeCallback(),this.closeCallback=void 0),this.applied=!1,this.frame.style.display="block",this._generateHueCircle()}},{key:"_hide",value:function(){var t=this;!0===(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&(this.previousColor=Nf({},this.color)),!0===this.applied&&this.updateCallback(this.initialColor),this.frame.style.display="none",Rv((function(){void 0!==t.closeCallback&&(t.closeCallback(),t.closeCallback=void 0)}),0)}},{key:"_save",value:function(){this.updateCallback(this.color),this.applied=!1,this._hide()}},{key:"_apply",value:function(){this.applied=!0,this.updateCallback(this.color),this._updatePicker(this.color)}},{key:"_loadLast",value:function(){void 0!==this.previousColor?this.setColor(this.previousColor,!1):alert("There is no last color to load...")}},{key:"_setColor",value:function(t){!0===(!(arguments.length>1&&void 0!==arguments[1])||arguments[1])&&(this.initialColor=Nf({},t)),this.color=t;var e=bb(t.r,t.g,t.b),i=2*Math.PI,n=this.r*e.s,r=this.centerCoordinates.x+n*Math.sin(i*e.h),o=this.centerCoordinates.y+n*Math.cos(i*e.h);this.colorPickerSelector.style.left=r-.5*this.colorPickerSelector.clientWidth+"px",this.colorPickerSelector.style.top=o-.5*this.colorPickerSelector.clientHeight+"px",this._updatePicker(t)}},{key:"_setOpacity",value:function(t){this.color.a=t/100,this._updatePicker(this.color)}},{key:"_setBrightness",value:function(t){var e=bb(this.color.r,this.color.g,this.color.b);e.v=t/100;var i=wb(e.h,e.s,e.v);i.a=this.color.a,this.color=i,this._updatePicker()}},{key:"_updatePicker",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.color,e=bb(t.r,t.g,t.b),i=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1)),i.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var n=this.colorPickerCanvas.clientWidth,r=this.colorPickerCanvas.clientHeight;i.clearRect(0,0,n,r),i.putImageData(this.hueCircle,0,0),i.fillStyle="rgba(0,0,0,"+(1-e.v)+")",i.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),Uv(i).call(i),this.brightnessRange.value=100*e.v,this.opacityRange.value=100*t.a,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}},{key:"_setSize",value:function(){this.colorPickerCanvas.style.width="100%",this.colorPickerCanvas.style.height="100%",this.colorPickerCanvas.width=289*this.pixelRatio,this.colorPickerCanvas.height=289*this.pixelRatio}},{key:"_create",value:function(){var t,e,i,n;if(this.frame=document.createElement("div"),this.frame.className="vis-color-picker",this.colorPickerDiv=document.createElement("div"),this.colorPickerSelector=document.createElement("div"),this.colorPickerSelector.className="vis-selector",this.colorPickerDiv.appendChild(this.colorPickerSelector),this.colorPickerCanvas=document.createElement("canvas"),this.colorPickerDiv.appendChild(this.colorPickerCanvas),this.colorPickerCanvas.getContext){var r=this.colorPickerCanvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(r.webkitBackingStorePixelRatio||r.mozBackingStorePixelRatio||r.msBackingStorePixelRatio||r.oBackingStorePixelRatio||r.backingStorePixelRatio||1),this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var o=document.createElement("DIV");o.style.color="red",o.style.fontWeight="bold",o.style.padding="10px",o.innerText="Error: your browser does not support HTML canvas",this.colorPickerCanvas.appendChild(o)}this.colorPickerDiv.className="vis-color",this.opacityDiv=document.createElement("div"),this.opacityDiv.className="vis-opacity",this.brightnessDiv=document.createElement("div"),this.brightnessDiv.className="vis-brightness",this.arrowDiv=document.createElement("div"),this.arrowDiv.className="vis-arrow",this.opacityRange=document.createElement("input");try{this.opacityRange.type="range",this.opacityRange.min="0",this.opacityRange.max="100"}catch(t){}this.opacityRange.value="100",this.opacityRange.className="vis-range",this.brightnessRange=document.createElement("input");try{this.brightnessRange.type="range",this.brightnessRange.min="0",this.brightnessRange.max="100"}catch(t){}this.brightnessRange.value="100",this.brightnessRange.className="vis-range",this.opacityDiv.appendChild(this.opacityRange),this.brightnessDiv.appendChild(this.brightnessRange);var s=this;this.opacityRange.onchange=function(){s._setOpacity(this.value)},this.opacityRange.oninput=function(){s._setOpacity(this.value)},this.brightnessRange.onchange=function(){s._setBrightness(this.value)},this.brightnessRange.oninput=function(){s._setBrightness(this.value)},this.brightnessLabel=document.createElement("div"),this.brightnessLabel.className="vis-label vis-brightness",this.brightnessLabel.innerText="brightness:",this.opacityLabel=document.createElement("div"),this.opacityLabel.className="vis-label vis-opacity",this.opacityLabel.innerText="opacity:",this.newColorDiv=document.createElement("div"),this.newColorDiv.className="vis-new-color",this.newColorDiv.innerText="new",this.initialColorDiv=document.createElement("div"),this.initialColorDiv.className="vis-initial-color",this.initialColorDiv.innerText="initial",this.cancelButton=document.createElement("div"),this.cancelButton.className="vis-button vis-cancel",this.cancelButton.innerText="cancel",this.cancelButton.onclick=Tp(t=this._hide).call(t,this,!1),this.applyButton=document.createElement("div"),this.applyButton.className="vis-button vis-apply",this.applyButton.innerText="apply",this.applyButton.onclick=Tp(e=this._apply).call(e,this),this.saveButton=document.createElement("div"),this.saveButton.className="vis-button vis-save",this.saveButton.innerText="save",this.saveButton.onclick=Tp(i=this._save).call(i,this),this.loadButton=document.createElement("div"),this.loadButton.className="vis-button vis-load",this.loadButton.innerText="load last",this.loadButton.onclick=Tp(n=this._loadLast).call(n,this),this.frame.appendChild(this.colorPickerDiv),this.frame.appendChild(this.arrowDiv),this.frame.appendChild(this.brightnessLabel),this.frame.appendChild(this.brightnessDiv),this.frame.appendChild(this.opacityLabel),this.frame.appendChild(this.opacityDiv),this.frame.appendChild(this.newColorDiv),this.frame.appendChild(this.initialColorDiv),this.frame.appendChild(this.cancelButton),this.frame.appendChild(this.applyButton),this.frame.appendChild(this.saveButton),this.frame.appendChild(this.loadButton)}},{key:"_bindHammer",value:function(){var t=this;this.drag={},this.pinch={},this.hammer=new Qy(this.colorPickerCanvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.on("hammer.input",(function(e){e.isFirst&&t._moveSelector(e)})),this.hammer.on("tap",(function(e){t._moveSelector(e)})),this.hammer.on("panstart",(function(e){t._moveSelector(e)})),this.hammer.on("panmove",(function(e){t._moveSelector(e)})),this.hammer.on("panend",(function(e){t._moveSelector(e)}))}},{key:"_generateHueCircle",value:function(){if(!1===this.generated){var t=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var e,i,n,r,o=this.colorPickerCanvas.clientWidth,s=this.colorPickerCanvas.clientHeight;t.clearRect(0,0,o,s),this.centerCoordinates={x:.5*o,y:.5*s},this.r=.49*o;var a,l=2*Math.PI/360,h=1/this.r;for(n=0;n<360;n++)for(r=0;r3&&void 0!==arguments[3]?arguments[3]:1,o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:function(){return!1};Ma(this,t),this.parent=e,this.changedOptions=[],this.container=i,this.allowCreation=!1,this.hideOption=o,this.options={},this.initialized=!1,this.popupCounter=0,this.defaultOptions={enabled:!1,filter:!0,container:void 0,showButton:!0},Nf(this.options,this.defaultOptions),this.configureOptions=n,this.moduleOptions={},this.domElements=[],this.popupDiv={},this.popupLimit=5,this.popupHistory={},this.colorPicker=new Ob(r),this.wrapper=void 0}return Yd(t,[{key:"setOptions",value:function(t){if(void 0!==t){this.popupHistory={},this._removePopup();var e=!0;if("string"==typeof t)this.options.filter=t;else if(qc(t))this.options.filter=t.join();else if("object"===Nd(t)){if(null==t)throw new TypeError("options cannot be null");void 0!==t.container&&(this.options.container=t.container),void 0!==mm(t)&&(this.options.filter=mm(t)),void 0!==t.showButton&&(this.options.showButton=t.showButton),void 0!==t.enabled&&(e=t.enabled)}else"boolean"==typeof t?(this.options.filter=!0,e=t):"function"==typeof t&&(this.options.filter=t,e=!0);!1===mm(this.options)&&(e=!1),this.options.enabled=e}this._clean()}},{key:"setModuleOptions",value:function(t){this.moduleOptions=t,!0===this.options.enabled&&(this._clean(),void 0!==this.options.container&&(this.container=this.options.container),this._create())}},{key:"_create",value:function(){this._clean(),this.changedOptions=[];var t=mm(this.options),e=0,i=!1;for(var n in this.configureOptions)Object.prototype.hasOwnProperty.call(this.configureOptions,n)&&(this.allowCreation=!1,i=!1,"function"==typeof t?i=(i=t(n,[]))||this._handleObject(this.configureOptions[n],[n],!0):!0!==t&&-1===av(t).call(t,n)||(i=!0),!1!==i&&(this.allowCreation=!0,e>0&&this._makeItem([]),this._makeHeader(n),this._handleObject(this.configureOptions[n],[n])),e++);this._makeButton(),this._push()}},{key:"_push",value:function(){this.wrapper=document.createElement("div"),this.wrapper.className="vis-configuration-wrapper",this.container.appendChild(this.wrapper);for(var t=0;t1?i-1:0),r=1;r2&&void 0!==arguments[2]&&arguments[2],n=document.createElement("div");if(n.className="vis-configuration vis-config-label vis-config-s"+e.length,!0===i){for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(Eb("i","b",t))}else n.innerText=t+":";return n}},{key:"_makeDropdown",value:function(t,e,i){var n=document.createElement("select");n.className="vis-configuration vis-config-select";var r=0;void 0!==e&&-1!==av(t).call(t,e)&&(r=av(t).call(t,e));for(var o=0;oo&&1!==o&&(a.max=Math.ceil(e*u),h=a.max,l="range increased"),a.value=e}else a.value=n;var d=document.createElement("input");d.className="vis-configuration vis-config-rangeinput",d.value=a.value;var c=this;a.onchange=function(){d.value=this.value,c._update(Number(this.value),i)},a.oninput=function(){d.value=this.value};var p=this._makeLabel(i[i.length-1],i),f=this._makeItem(i,p,a,d);""!==l&&this.popupHistory[f]!==h&&(this.popupHistory[f]=h,this._setupPopup(l,f))}},{key:"_makeButton",value:function(){var t=this;if(!0===this.options.showButton){var e=document.createElement("div");e.className="vis-configuration vis-config-button",e.innerText="generate options",e.onclick=function(){t._printOptions()},e.onmouseover=function(){e.className="vis-configuration vis-config-button hover"},e.onmouseout=function(){e.className="vis-configuration vis-config-button"},this.optionsContainer=document.createElement("div"),this.optionsContainer.className="vis-configuration vis-config-option-container",this.domElements.push(this.optionsContainer),this.domElements.push(e)}}},{key:"_setupPopup",value:function(t,e){var i=this;if(!0===this.initialized&&!0===this.allowCreation&&this.popupCounter1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=!1,r=mm(this.options),o=!1;for(var s in t)if(Object.prototype.hasOwnProperty.call(t,s)){n=!0;var a=t[s],l=pb(e,s);if("function"==typeof r&&!1===(n=r(s,e))&&!qc(a)&&"string"!=typeof a&&"boolean"!=typeof a&&a instanceof Object&&(this.allowCreation=!1,n=this._handleObject(a,l,!0),this.allowCreation=!1===i),!1!==n){o=!0;var h=this._getValue(l);if(qc(a))this._handleArray(a,h,l);else if("string"==typeof a)this._makeTextInput(a,h,l);else if("boolean"==typeof a)this._makeCheckbox(a,h,l);else if(a instanceof Object){if(!this.hideOption(e,s,this.moduleOptions))if(void 0!==a.enabled){var u=pb(l,"enabled"),d=this._getValue(u);if(!0===d){var c=this._makeLabel(s,l,!0);this._makeItem(l,c),o=this._handleObject(a,l)||o}else this._makeCheckbox(a,d,l)}else{var p=this._makeLabel(s,l,!0);this._makeItem(l,p),o=this._handleObject(a,l)||o}}else console.error("dont know how to handle",a,s,l)}}return o}},{key:"_handleArray",value:function(t,e,i){"string"==typeof t[0]&&"color"===t[0]?(this._makeColorField(t,e,i),t[1]!==e&&this.changedOptions.push({path:i,value:e})):"string"==typeof t[0]?(this._makeDropdown(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:e})):"number"==typeof t[0]&&(this._makeRange(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:Number(e)}))}},{key:"_update",value:function(t,e){var i=this._constructOptions(t,e);this.parent.body&&this.parent.body.emitter&&this.parent.body.emitter.emit&&this.parent.body.emitter.emit("configChange",i),this.initialized=!0,this.parent.setOptions(i)}},{key:"_constructOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=i;t="false"!==(t="true"===t||t)&&t;for(var r=0;rr-this.padding&&(a=!0),o=a?this.x-i:this.x,s=l?this.y-e:this.y}else(s=this.y-e)+e+this.padding>n&&(s=n-e-this.padding),sr&&(o=r-i-this.padding),os.distance?" in "+t.printLocation(o.path,e,"")+"Perhaps it was misplaced? Matching option found at: "+t.printLocation(s.path,s.closestMatch,""):o.distance<=8?'. Did you mean "'+o.closestMatch+'"?'+t.printLocation(o.path,e):". Did you mean one of these: "+t.print(rp(i))+t.printLocation(n,e),console.error('%cUnknown option detected: "'+e+'"'+r,Nb),Lb=!0}},{key:"findInOptions",value:function(e,i,n){var r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],o=1e9,s="",a=[],l=e.toLowerCase(),h=void 0;for(var u in i){var d=void 0;if(void 0!==i[u].__type__&&!0===r){var c=t.findInOptions(e,i[u],pb(n,u));o>c.distance&&(s=c.closestMatch,a=c.path,o=c.distance,h=c.indexMatch)}else{var p;-1!==av(p=u.toLowerCase()).call(p,l)&&(h=u),o>(d=t.levenshteinDistance(e,u))&&(s=u,a=fb(n),o=d)}}return{closestMatch:s,path:a,distance:o,indexMatch:h}}},{key:"printLocation",value:function(t,e){for(var i="\n\n"+(arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Problem value found at: \n")+"options = {\n",n=0;n>>0,t=(r*=t)>>>0,t+=4294967296*(r-=t)}return 2.3283064365386963e-10*(t>>>0)}}(),e=t(" "),i=t(" "),n=t(" "),r=0;r0)return"before"==n?Math.max(0,l-1):l;if(r(s,e)<0&&r(a,e)>0)return"before"==n?l:Math.min(t.length-1,l+1);r(s,e)<0?u=l+1:d=l-1,h++}return-1},bridgeObject:Tb,copyAndExtendArray:pb,copyArray:fb,deepExtend:db,deepObjectAssign:$y,easingFunctions:{linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return t*(2-t)},easeInOutQuad:function(t){return t<.5?2*t*t:(4-2*t)*t-1},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return--t*t*t+1},easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return 1- --t*t*t*t},easeInOutQuart:function(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return 1+--t*t*t*t*t},easeInOutQuint:function(t){return t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t}},equalArray:function(t,e){if(t.length!==e.length)return!1;for(var i=0,n=t.length;i2&&void 0!==arguments[2]&&arguments[2];for(var r in e)if(void 0!==i[r])if(null===i[r]||"object"!==Nd(i[r]))hb(e,i,r,n);else{var o=e[r],s=i[r];lb(o)&&lb(s)&&t(o,s,n)}},forEach:function(t,e){if(qc(t))for(var i=t.length,n=0;n0&&void 0!==arguments[0]?arguments[0]:window.event,e=null;return t&&(t.target?e=t.target:t.srcElement&&(e=t.srcElement)),e instanceof Element&&(null==e.nodeType||3!=e.nodeType||(e=e.parentNode)instanceof Element)?e:null},getType:cb,hasParent:function(t,e){for(var i=t;i;){if(i===e)return!0;if(!i.parentNode)return!1;i=i.parentNode}return!1},hexToHSV:xb,hexToRGB:gb,insertSort:function(t,e){for(var i=0;i0&&e(n,t[r-1])<0;r--)t[r]=t[r-1];t[r]=n}return t},isDate:function(t){if(t instanceof Date)return!0;if(ab(t)){if(eb.exec(t))return!0;if(!isNaN(Date.parse(t)))return!0}return!1},isNumber:sb,isObject:lb,isString:ab,isValidHex:Db,isValidRGB:Sb,isValidRGBA:Cb,mergeOptions:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},r=function(t){return null!=t},o=function(t){return null!==t&&"object"===Nd(t)};if(!o(t))throw new Error("Parameter mergeTarget must be an object");if(!o(e))throw new Error("Parameter options must be an object");if(!r(i))throw new Error("Parameter option must have a value");if(!o(n))throw new Error("Parameter globalOptions must be an object");var s=e[i],a=o(n)&&!function(t){for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e))return!1;return!0}(n)?n[i]:void 0,l=a?a.enabled:void 0;if(void 0!==s){if("boolean"==typeof s)return o(t[i])||(t[i]={}),void(t[i].enabled=s);if(null===s&&!o(t[i])){if(!r(a))return;t[i]=cv(a)}if(o(s)){var h=!0;void 0!==s.enabled?h=s.enabled:void 0!==l&&(h=a.enabled),function(t,e,i){o(t[i])||(t[i]={});var n=e[i],r=t[i];for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(r[s]=n[s])}(t,e,i),t[i].enabled=h}}},option:vb,overrideOpacity:function(t,e){if(nm(t).call(t,"rgba"))return t;if(nm(t).call(t,"rgb")){var i=t.substr(av(t).call(t,"(")+1).replace(")","").split(",");return"rgba("+i[0]+","+i[1]+","+i[2]+","+e+")"}var n=gb(t);return null==n?t:"rgba("+n.r+","+n.g+","+n.b+","+e+")"},parseColor:function(t,e){if(ab(t)){var i=t;if(Sb(i)){var n,r=ep(n=i.substr(4).substr(0,i.length-5).split(",")).call(n,(function(t){return Zm(t)}));i=yb(r[0],r[1],r[2])}if(!0===Db(i)){var o=xb(i),s={h:o.h,s:.8*o.s,v:Math.min(1,1.02*o.v)},a={h:o.h,s:Math.min(1,1.25*o.s),v:.8*o.v},l=kb(a.h,a.s,a.v),h=kb(s.h,s.s,s.v);return{background:i,border:l,highlight:{background:h,border:l},hover:{background:h,border:l}}}return{background:i,border:i,highlight:{background:i,border:i},hover:{background:i,border:i}}}return e?{background:t.background||e.background,border:t.border||e.border,highlight:ab(t.highlight)?{border:t.highlight,background:t.highlight}:{background:t.highlight&&t.highlight.background||e.highlight.background,border:t.highlight&&t.highlight.border||e.highlight.border},hover:ab(t.hover)?{border:t.hover,background:t.hover}:{border:t.hover&&t.hover.border||e.hover.border,background:t.hover&&t.hover.background||e.hover.background}}:{background:t.background||void 0,border:t.border||void 0,highlight:ab(t.highlight)?{border:t.highlight,background:t.highlight}:{background:t.highlight&&t.highlight.background||void 0,border:t.highlight&&t.highlight.border||void 0},hover:ab(t.hover)?{border:t.hover,background:t.hover}:{border:t.hover&&t.hover.border||void 0,background:t.hover&&t.hover.background||void 0}}},preventDefault:function(t){t||(t=window.event),t&&(t.preventDefault?t.preventDefault():t.returnValue=!1)},pureDeepObjectAssign:qy,recursiveDOMDelete:function t(e){if(e)for(;!0===e.hasChildNodes();){var i=e.firstChild;i&&(t(i),e.removeChild(i))}},removeClassName:function(t,e){var i=t.className.split(" "),n=e.split(" ");i=mm(i).call(i,(function(t){return!nm(n).call(n,t)})),t.className=i.join(" ")},removeCssText:function(t,e){for(var i=_b(e),n=0,r=rp(i);n3&&void 0!==arguments[3]&&arguments[3];if(qc(i))throw new TypeError("Arrays are not supported by deepExtend");for(var r=0;r2?i-2:0),r=2;r3&&void 0!==arguments[3]&&arguments[3];if(qc(i))throw new TypeError("Arrays are not supported by deepExtend");for(var r in i)if(Object.prototype.hasOwnProperty.call(i,r)&&!nm(t).call(t,r))if(i[r]&&i[r].constructor===Object)void 0===e[r]&&(e[r]={}),e[r].constructor===Object?db(e[r],i[r]):hb(e,i,r,n);else if(qc(i[r])){e[r]=[];for(var o=0;o0?(n=e[t].redundant[0],e[t].redundant.shift()):(n=document.createElementNS("http://www.w3.org/2000/svg",t),i.appendChild(n)):(n=document.createElementNS("http://www.w3.org/2000/svg",t),e[t]={used:[],redundant:[]},i.appendChild(n)),e[t].used.push(n),n}function $b(t,e,i,n){var r;return e.hasOwnProperty(t)?e[t].redundant.length>0?(r=e[t].redundant[0],e[t].redundant.shift()):(r=document.createElement(t),void 0!==n?i.insertBefore(r,n):i.appendChild(r)):(r=document.createElement(t),e[t]={used:[],redundant:[]},void 0!==n?i.insertBefore(r,n):i.appendChild(r)),e[t].used.push(r),r}function Zb(t,e,i,n,r,o){var s;if("circle"==i.style?((s=qb("circle",n,r)).setAttributeNS(null,"cx",t),s.setAttributeNS(null,"cy",e),s.setAttributeNS(null,"r",.5*i.size)):((s=qb("rect",n,r)).setAttributeNS(null,"x",t-.5*i.size),s.setAttributeNS(null,"y",e-.5*i.size),s.setAttributeNS(null,"width",i.size),s.setAttributeNS(null,"height",i.size)),void 0!==i.styles&&s.setAttributeNS(null,"style",i.styles),s.setAttributeNS(null,"class",i.className+" vis-point"),o){var a=qb("text",n,r);o.xOffset&&(t+=o.xOffset),o.yOffset&&(e+=o.yOffset),o.content&&(a.textContent=o.content),o.className&&a.setAttributeNS(null,"class",o.className+" vis-label"),a.setAttributeNS(null,"x",t),a.setAttributeNS(null,"y",e)}return s}function Kb(t,e,i,n,r,o,s,a){if(0!=n){n<0&&(e-=n*=-1);var l=qb("rect",o,s);l.setAttributeNS(null,"x",t-.5*i),l.setAttributeNS(null,"y",e),l.setAttributeNS(null,"width",i),l.setAttributeNS(null,"height",n),l.setAttributeNS(null,"class",r),a&&l.setAttributeNS(null,"style",a)}}function Jb(){try{return navigator?navigator.languages&&navigator.languages.length?navigator.languages:navigator.userLanguage||navigator.language||navigator.browserLanguage||"en":"en"}catch(t){return"en"}}var Qb=Object.freeze({__proto__:null,cleanupElements:Ub,drawBar:Kb,drawPoint:Zb,getDOMElement:$b,getNavigatorLanguage:Jb,getSVGElement:qb,prepareElements:Vb,resetElements:Xb});function t_(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}var e_=dv,i_=n(e_);En({target:"Object",stat:!0},{setPrototypeOf:Do});var n_=ce.Object.setPrototypeOf,r_=n(n_),o_=n(Cp);function s_(t,e){var i;return s_=r_?o_(i=r_).call(i):function(t,e){return t.__proto__=e,t},s_(t,e)}function a_(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=i_(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Fa(t,"prototype",{writable:!1}),e&&s_(t,e)}function l_(t,e){if(e&&("object"===Nd(e)||"function"==typeof e))return e;if(void 0!==e)throw new TypeError("Derived constructors may only return object or undefined");return t_(t)}var h_=am,u_=n(h_);function d_(t){var e;return d_=r_?o_(e=u_).call(e):function(t){return t.__proto__||u_(t)},d_(t)}function c_(t,e,i){return(e=Fd(e))in t?Fa(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}var p_={exports:{}},f_={exports:{}};!function(t){var e=Ed,i=Id;function n(r){return t.exports=n="function"==typeof e&&"symbol"==typeof i?function(t){return typeof t}:function(t){return t&&"function"==typeof e&&t.constructor===e&&t!==e.prototype?"symbol":typeof t},t.exports.__esModule=!0,t.exports.default=t.exports,n(r)}t.exports=n,t.exports.__esModule=!0,t.exports.default=t.exports}(f_);var m_=f_.exports,v_=Yp,g_=z,y_=Uc,b_=Fi,__=Kt,w_=$t,k_=ui,x_=Error,D_=m("".replace),S_=String(new x_("zxcasd").stack),C_=/\n\s*at [^:]*:[^\n]*/,T_=C_.test(S_),M_=ai,O_=!h((function(){var t=new Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",M_(1,7)),7!==t.stack)})),E_=ui,P_=function(t,e){if(T_&&"string"==typeof t&&!x_.prepareStackTrace)for(;e--;)t=D_(t,C_,"");return t},A_=O_,I_=Error.captureStackTrace,L_=yn,N_=de,R_=le,F_=Se,j_=ss,Y_=Vn,H_=ye,z_=zs,B_=Ls,G_=ts,W_=TypeError,V_=function(t,e){this.stopped=t,this.result=e},U_=V_.prototype,X_=function(t,e,i){var n,r,o,s,a,l,h,u=i&&i.that,d=!(!i||!i.AS_ENTRIES),c=!(!i||!i.IS_RECORD),p=!(!i||!i.IS_ITERATOR),f=!(!i||!i.INTERRUPTED),m=L_(e,u),v=function(t){return n&&G_(n,"normal",t),new V_(!0,t)},g=function(t){return d?(R_(t),f?m(t[0],t[1],v):m(t[0],t[1])):f?m(t,v):m(t)};if(c)n=t.iterator;else if(p)n=t;else{if(!(r=B_(t)))throw new W_(F_(t)+" is not iterable");if(j_(r)){for(o=0,s=Y_(t);s>o;o++)if((a=g(t[o]))&&H_(U_,a))return a;return new V_(!1)}n=z_(t,r)}for(l=c?t.next:n.next;!(h=N_(l,n)).done;){try{a=g(h.value)}catch(t){G_(n,"throw",t)}if("object"==typeof a&&a&&H_(U_,a))return a}return new V_(!1)},q_=Lt,$_=En,Z_=ye,K_=Hr,J_=Do,Q_=function(t,e,i){for(var n=y_(e),r=__.f,o=b_.f,s=0;s2&&nw(i,arguments[2]);var r=[];return ow(t,hw,{that:r}),ew(i,"errors",r),i};J_?J_(uw,lw):Q_(uw,lw,{name:!0});var dw=uw.prototype=tw(lw.prototype,{constructor:iw(1,uw),message:iw(1,""),name:iw(1,"AggregateError")});$_({global:!0,constructor:!0,arity:2},{AggregateError:uw});var cw,pw,fw,mw,vw="process"===Dt(w.process),gw=ge,yw=El,bw=Zt,_w=ft("species"),ww=function(t){var e=gw(t);bw&&e&&!e[_w]&&yw(e,_w,{configurable:!0,get:function(){return this}})},kw=ye,xw=TypeError,Dw=function(t,e){if(kw(e,t))return t;throw new xw("Incorrect invocation")},Sw=Ds,Cw=Se,Tw=TypeError,Mw=function(t){if(Sw(t))return t;throw new Tw(Cw(t)+" is not a constructor")},Ow=le,Ew=Mw,Pw=A,Aw=ft("species"),Iw=function(t,e){var i,n=Ow(t).constructor;return void 0===n||Pw(i=Ow(n)[Aw])?e:Ew(i)},Lw=/(?:ipad|iphone|ipod).*applewebkit/i.test(X),Nw=w,Rw=Ii,Fw=yn,jw=_t,Yw=z,Hw=h,zw=fr,Bw=ku,Gw=ee,Ww=bv,Vw=Lw,Uw=vw,Xw=Nw.setImmediate,qw=Nw.clearImmediate,$w=Nw.process,Zw=Nw.Dispatch,Kw=Nw.Function,Jw=Nw.MessageChannel,Qw=Nw.String,tk=0,ek={},ik="onreadystatechange";Hw((function(){cw=Nw.location}));var nk=function(t){if(Yw(ek,t)){var e=ek[t];delete ek[t],e()}},rk=function(t){return function(){nk(t)}},ok=function(t){nk(t.data)},sk=function(t){Nw.postMessage(Qw(t),cw.protocol+"//"+cw.host)};Xw&&qw||(Xw=function(t){Ww(arguments.length,1);var e=jw(t)?t:Kw(t),i=Bw(arguments,1);return ek[++tk]=function(){Rw(e,void 0,i)},pw(tk),tk},qw=function(t){delete ek[t]},Uw?pw=function(t){$w.nextTick(rk(t))}:Zw&&Zw.now?pw=function(t){Zw.now(rk(t))}:Jw&&!Vw?(mw=(fw=new Jw).port2,fw.port1.onmessage=ok,pw=Fw(mw.postMessage,mw)):Nw.addEventListener&&jw(Nw.postMessage)&&!Nw.importScripts&&cw&&"file:"!==cw.protocol&&!Hw(sk)?(pw=sk,Nw.addEventListener("message",ok,!1)):pw=ik in Gw("script")?function(t){zw.appendChild(Gw("script"))[ik]=function(){zw.removeChild(this),nk(t)}}:function(t){setTimeout(rk(t),0)});var ak={set:Xw,clear:qw},lk=function(){this.head=null,this.tail=null};lk.prototype={add:function(t){var e={item:t,next:null},i=this.tail;i?i.next=e:this.head=e,this.tail=e},get:function(){var t=this.head;if(t)return null===(this.head=t.next)&&(this.tail=null),t.item}};var hk,uk,dk,ck,pk,fk=lk,mk=/ipad|iphone|ipod/i.test(X)&&"undefined"!=typeof Pebble,vk=/web0s(?!.*chrome)/i.test(X),gk=w,yk=yn,bk=Fi.f,_k=ak.set,wk=fk,kk=Lw,xk=mk,Dk=vk,Sk=vw,Ck=gk.MutationObserver||gk.WebKitMutationObserver,Tk=gk.document,Mk=gk.process,Ok=gk.Promise,Ek=bk(gk,"queueMicrotask"),Pk=Ek&&Ek.value;if(!Pk){var Ak=new wk,Ik=function(){var t,e;for(Sk&&(t=Mk.domain)&&t.exit();e=Ak.get();)try{e()}catch(t){throw Ak.head&&hk(),t}t&&t.enter()};kk||Sk||Dk||!Ck||!Tk?!xk&&Ok&&Ok.resolve?((ck=Ok.resolve(void 0)).constructor=Ok,pk=yk(ck.then,ck),hk=function(){pk(Ik)}):Sk?hk=function(){Mk.nextTick(Ik)}:(_k=yk(_k,gk),hk=function(){_k(Ik)}):(uk=!0,dk=Tk.createTextNode(""),new Ck(Ik).observe(dk,{characterData:!0}),hk=function(){dk.data=uk=!uk}),Pk=function(t){Ak.head||hk(),Ak.add(t)}}var Lk=Pk,Nk=function(t){try{return{error:!1,value:t()}}catch(t){return{error:!0,value:t}}},Rk=w.Promise,Fk="object"==typeof Deno&&Deno&&"object"==typeof Deno.version,jk=!Fk&&!vw&&"object"==typeof window&&"object"==typeof document,Yk=w,Hk=Rk,zk=_t,Bk=fn,Gk=us,Wk=ft,Vk=jk,Uk=Fk,Xk=tt,qk=Hk&&Hk.prototype,$k=Wk("species"),Zk=!1,Kk=zk(Yk.PromiseRejectionEvent),Jk=Bk("Promise",(function(){var t=Gk(Hk),e=t!==String(Hk);if(!e&&66===Xk)return!0;if(!qk.catch||!qk.finally)return!0;if(!Xk||Xk<51||!/native code/.test(t)){var i=new Hk((function(t){t(1)})),n=function(t){t((function(){}),(function(){}))};if((i.constructor={})[$k]=n,!(Zk=i.then((function(){}))instanceof n))return!0}return!e&&(Vk||Uk)&&!Kk})),Qk={CONSTRUCTOR:Jk,REJECTION_EVENT:Kk,SUBCLASSING:Zk},tx={},ex=Oe,ix=TypeError,nx=function(t){var e,i;this.promise=new t((function(t,n){if(void 0!==e||void 0!==i)throw new ix("Bad Promise constructor");e=t,i=n})),this.resolve=ex(e),this.reject=ex(i)};tx.f=function(t){return new nx(t)};var rx,ox,sx=En,ax=vw,lx=w,hx=de,ux=Br,dx=ao,cx=ww,px=Oe,fx=_t,mx=$t,vx=Dw,gx=Iw,yx=ak.set,bx=Lk,_x=function(t,e){try{1===arguments.length?console.error(t):console.error(t,e)}catch(t){}},wx=Nk,kx=fk,xx=Mi,Dx=Rk,Sx=Qk,Cx=tx,Tx="Promise",Mx=Sx.CONSTRUCTOR,Ox=Sx.REJECTION_EVENT,Ex=xx.getterFor(Tx),Px=xx.set,Ax=Dx&&Dx.prototype,Ix=Dx,Lx=Ax,Nx=lx.TypeError,Rx=lx.document,Fx=lx.process,jx=Cx.f,Yx=jx,Hx=!!(Rx&&Rx.createEvent&&lx.dispatchEvent),zx="unhandledrejection",Bx=function(t){var e;return!(!mx(t)||!fx(e=t.then))&&e},Gx=function(t,e){var i,n,r,o=e.value,s=1===e.state,a=s?t.ok:t.fail,l=t.resolve,h=t.reject,u=t.domain;try{a?(s||(2===e.rejection&&qx(e),e.rejection=1),!0===a?i=o:(u&&u.enter(),i=a(o),u&&(u.exit(),r=!0)),i===t.promise?h(new Nx("Promise-chain cycle")):(n=Bx(i))?hx(n,i,l,h):l(i)):h(o)}catch(t){u&&!r&&u.exit(),h(t)}},Wx=function(t,e){t.notified||(t.notified=!0,bx((function(){for(var i,n=t.reactions;i=n.get();)Gx(i,t);t.notified=!1,e&&!t.rejection&&Ux(t)})))},Vx=function(t,e,i){var n,r;Hx?((n=Rx.createEvent("Event")).promise=e,n.reason=i,n.initEvent(t,!1,!0),lx.dispatchEvent(n)):n={promise:e,reason:i},!Ox&&(r=lx["on"+t])?r(n):t===zx&&_x("Unhandled promise rejection",i)},Ux=function(t){hx(yx,lx,(function(){var e,i=t.facade,n=t.value;if(Xx(t)&&(e=wx((function(){ax?Fx.emit("unhandledRejection",n,i):Vx(zx,i,n)})),t.rejection=ax||Xx(t)?2:1,e.error))throw e.value}))},Xx=function(t){return 1!==t.rejection&&!t.parent},qx=function(t){hx(yx,lx,(function(){var e=t.facade;ax?Fx.emit("rejectionHandled",e):Vx("rejectionhandled",e,t.value)}))},$x=function(t,e,i){return function(n){t(e,n,i)}},Zx=function(t,e,i){t.done||(t.done=!0,i&&(t=i),t.value=e,t.state=2,Wx(t,!0))},Kx=function(t,e,i){if(!t.done){t.done=!0,i&&(t=i);try{if(t.facade===e)throw new Nx("Promise can't be resolved itself");var n=Bx(e);n?bx((function(){var i={done:!1};try{hx(n,e,$x(Kx,i,t),$x(Zx,i,t))}catch(e){Zx(i,e,t)}})):(t.value=e,t.state=1,Wx(t,!1))}catch(e){Zx({done:!1},e,t)}}};Mx&&(Lx=(Ix=function(t){vx(this,Lx),px(t),hx(rx,this);var e=Ex(this);try{t($x(Kx,e),$x(Zx,e))}catch(t){Zx(e,t)}}).prototype,(rx=function(t){Px(this,{type:Tx,done:!1,notified:!1,parent:!1,reactions:new kx,rejection:!1,state:0,value:void 0})}).prototype=ux(Lx,"then",(function(t,e){var i=Ex(this),n=jx(gx(this,Ix));return i.parent=!0,n.ok=!fx(t)||t,n.fail=fx(e)&&e,n.domain=ax?Fx.domain:void 0,0===i.state?i.reactions.add(n):bx((function(){Gx(n,i)})),n.promise})),ox=function(){var t=new rx,e=Ex(t);this.promise=t,this.resolve=$x(Kx,e),this.reject=$x(Zx,e)},Cx.f=jx=function(t){return t===Ix||undefined===t?new ox(t):Yx(t)}),sx({global:!0,constructor:!0,wrap:!0,forced:Mx},{Promise:Ix}),dx(Ix,Tx,!1,!0),cx(Tx);var Jx=Rk,Qx=Qk.CONSTRUCTOR||!na((function(t){Jx.all(t).then(void 0,(function(){}))})),tD=de,eD=Oe,iD=tx,nD=Nk,rD=X_;En({target:"Promise",stat:!0,forced:Qx},{all:function(t){var e=this,i=iD.f(e),n=i.resolve,r=i.reject,o=nD((function(){var i=eD(e.resolve),o=[],s=0,a=1;rD(t,(function(t){var l=s++,h=!1;a++,tD(i,e,t).then((function(t){h||(h=!0,o[l]=t,--a||n(o))}),r)})),--a||n(o)}));return o.error&&r(o.value),i.promise}});var oD=En,sD=Qk.CONSTRUCTOR;Rk&&Rk.prototype,oD({target:"Promise",proto:!0,forced:sD,real:!0},{catch:function(t){return this.then(void 0,t)}});var aD=de,lD=Oe,hD=tx,uD=Nk,dD=X_;En({target:"Promise",stat:!0,forced:Qx},{race:function(t){var e=this,i=hD.f(e),n=i.reject,r=uD((function(){var r=lD(e.resolve);dD(t,(function(t){aD(r,e,t).then(i.resolve,n)}))}));return r.error&&n(r.value),i.promise}});var cD=de,pD=tx;En({target:"Promise",stat:!0,forced:Qk.CONSTRUCTOR},{reject:function(t){var e=pD.f(this);return cD(e.reject,void 0,t),e.promise}});var fD=le,mD=$t,vD=tx,gD=function(t,e){if(fD(t),mD(e)&&e.constructor===t)return e;var i=vD.f(t);return(0,i.resolve)(e),i.promise},yD=En,bD=Rk,_D=Qk.CONSTRUCTOR,wD=gD,kD=ge("Promise"),xD=!_D;yD({target:"Promise",stat:!0,forced:true},{resolve:function(t){return wD(xD&&this===kD?bD:this,t)}});var DD=de,SD=Oe,CD=tx,TD=Nk,MD=X_;En({target:"Promise",stat:!0,forced:Qx},{allSettled:function(t){var e=this,i=CD.f(e),n=i.resolve,r=i.reject,o=TD((function(){var i=SD(e.resolve),r=[],o=0,s=1;MD(t,(function(t){var a=o++,l=!1;s++,DD(i,e,t).then((function(t){l||(l=!0,r[a]={status:"fulfilled",value:t},--s||n(r))}),(function(t){l||(l=!0,r[a]={status:"rejected",reason:t},--s||n(r))}))})),--s||n(r)}));return o.error&&r(o.value),i.promise}});var OD=de,ED=Oe,PD=ge,AD=tx,ID=Nk,LD=X_,ND="No one promise resolved";En({target:"Promise",stat:!0,forced:Qx},{any:function(t){var e=this,i=PD("AggregateError"),n=AD.f(e),r=n.resolve,o=n.reject,s=ID((function(){var n=ED(e.resolve),s=[],a=0,l=1,h=!1;LD(t,(function(t){var u=a++,d=!1;l++,OD(n,e,t).then((function(t){d||h||(h=!0,r(t))}),(function(t){d||h||(d=!0,s[u]=t,--l||o(new i(s,ND)))}))})),--l||o(new i(s,ND))}));return s.error&&o(s.value),n.promise}});var RD=En,FD=Rk,jD=h,YD=ge,HD=_t,zD=Iw,BD=gD,GD=FD&&FD.prototype;RD({target:"Promise",proto:!0,real:!0,forced:!!FD&&jD((function(){GD.finally.call({then:function(){}},(function(){}))}))},{finally:function(t){var e=zD(this,YD("Promise")),i=HD(t);return this.then(i?function(i){return BD(e,t()).then((function(){return i}))}:t,i?function(i){return BD(e,t()).then((function(){throw i}))}:t)}});var WD=ce.Promise,VD=tx;En({target:"Promise",stat:!0},{withResolvers:function(){var t=VD.f(this);return{promise:t.promise,resolve:t.resolve,reject:t.reject}}});var UD=WD,XD=tx,qD=Nk;En({target:"Promise",stat:!0,forced:!0},{try:function(t){var e=XD.f(this),i=qD(t);return(i.error?e.reject:e.resolve)(i.value),e.promise}});var $D=UD,ZD=Zp;!function(t){var e=m_.default,i=Ra,n=Ed,r=e_,o=h_,s=v_,a=rc,l=n_,h=$D,u=ZD,d=Cc;function c(){t.exports=c=function(){return f},t.exports.__esModule=!0,t.exports.default=t.exports;var p,f={},m=Object.prototype,v=m.hasOwnProperty,g=i||function(t,e,i){t[e]=i.value},y="function"==typeof n?n:{},b=y.iterator||"@@iterator",_=y.asyncIterator||"@@asyncIterator",w=y.toStringTag||"@@toStringTag";function k(t,e,n){return i(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{k({},"")}catch(p){k=function(t,e,i){return t[e]=i}}function x(t,e,i,n){var o=e&&e.prototype instanceof E?e:E,s=r(o.prototype),a=new B(n||[]);return g(s,"_invoke",{value:j(t,i,a)}),s}function D(t,e,i){try{return{type:"normal",arg:t.call(e,i)}}catch(t){return{type:"throw",arg:t}}}f.wrap=x;var S="suspendedStart",C="suspendedYield",T="executing",M="completed",O={};function E(){}function P(){}function A(){}var I={};k(I,b,(function(){return this}));var L=o&&o(o(G([])));L&&L!==m&&v.call(L,b)&&(I=L);var N=A.prototype=E.prototype=r(I);function R(t){var e;s(e=["next","throw","return"]).call(e,(function(e){k(t,e,(function(t){return this._invoke(e,t)}))}))}function F(t,i){function n(r,o,s,a){var l=D(t[r],t,o);if("throw"!==l.type){var h=l.arg,u=h.value;return u&&"object"==e(u)&&v.call(u,"__await")?i.resolve(u.__await).then((function(t){n("next",t,s,a)}),(function(t){n("throw",t,s,a)})):i.resolve(u).then((function(t){h.value=t,s(h)}),(function(t){return n("throw",t,s,a)}))}a(l.arg)}var r;g(this,"_invoke",{value:function(t,e){function o(){return new i((function(i,r){n(t,e,i,r)}))}return r=r?r.then(o,o):o()}})}function j(t,e,i){var n=S;return function(r,o){if(n===T)throw new Error("Generator is already running");if(n===M){if("throw"===r)throw o;return{value:p,done:!0}}for(i.method=r,i.arg=o;;){var s=i.delegate;if(s){var a=Y(s,i);if(a){if(a===O)continue;return a}}if("next"===i.method)i.sent=i._sent=i.arg;else if("throw"===i.method){if(n===S)throw n=M,i.arg;i.dispatchException(i.arg)}else"return"===i.method&&i.abrupt("return",i.arg);n=T;var l=D(t,e,i);if("normal"===l.type){if(n=i.done?M:C,l.arg===O)continue;return{value:l.arg,done:i.done}}"throw"===l.type&&(n=M,i.method="throw",i.arg=l.arg)}}}function Y(t,e){var i=e.method,n=t.iterator[i];if(n===p)return e.delegate=null,"throw"===i&&t.iterator.return&&(e.method="return",e.arg=p,Y(t,e),"throw"===e.method)||"return"!==i&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+i+"' method")),O;var r=D(n,t.iterator,e.arg);if("throw"===r.type)return e.method="throw",e.arg=r.arg,e.delegate=null,O;var o=r.arg;return o?o.done?(e[t.resultName]=o.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=p),e.delegate=null,O):o:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,O)}function H(t){var e,i={tryLoc:t[0]};1 in t&&(i.catchLoc=t[1]),2 in t&&(i.finallyLoc=t[2],i.afterLoc=t[3]),a(e=this.tryEntries).call(e,i)}function z(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function B(t){this.tryEntries=[{tryLoc:"root"}],s(t).call(t,H,this),this.reset(!0)}function G(t){if(t||""===t){var i=t[b];if(i)return i.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,r=function e(){for(;++n=0;--n){var r=this.tryEntries[n],o=r.completion;if("root"===r.tryLoc)return i("end");if(r.tryLoc<=this.prev){var s=v.call(r,"catchLoc"),a=v.call(r,"finallyLoc");if(s&&a){if(this.prev=0;--i){var n=this.tryEntries[i];if(n.tryLoc<=this.prev&&v.call(n,"finallyLoc")&&this.prev=0;--e){var i=this.tryEntries[e];if(i.finallyLoc===t)return this.complete(i.completion,i.afterLoc),z(i),O}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var i=this.tryEntries[e];if(i.tryLoc===t){var n=i.completion;if("throw"===n.type){var r=n.arg;z(i)}return r}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,i){return this.delegate={iterator:G(t),resultName:e,nextLoc:i},"next"===this.method&&(this.arg=p),O}},f}t.exports=c,t.exports.__esModule=!0,t.exports.default=t.exports}(p_);var KD=(0,p_.exports)(),JD=KD;try{regeneratorRuntime=KD}catch(t){"object"==typeof globalThis?globalThis.regeneratorRuntime=KD:Function("r","regeneratorRuntime = r")(KD)}var QD=n(JD),tS=Oe,eS=j,iS=Ui,nS=Vn,rS=TypeError,oS=function(t){return function(e,i,n,r){tS(i);var o=eS(e),s=iS(o),a=nS(o),l=t?a-1:0,h=t?-1:1;if(n<2)for(;;){if(l in s){r=s[l],l+=h;break}if(l+=h,t?l<0:a<=l)throw new rS("Reduce of empty array with no initial value")}for(;t?l>=0:a>l;l+=h)l in s&&(r=i(r,s[l],l,o));return r}},sS={left:oS(!1),right:oS(!0)}.left;En({target:"Array",proto:!0,forced:!vw&&tt>79&&tt<83||!Op("reduce")},{reduce:function(t){var e=arguments.length;return sS(this,t,e,e>1?arguments[1]:void 0)}});var aS=Jd("Array").reduce,lS=ye,hS=aS,uS=Array.prototype,dS=function(t){var e=t.reduce;return t===uS||lS(uS,t)&&e===uS.reduce?hS:e},cS=n(dS),pS=Ya,fS=Vn,mS=za,vS=yn,gS=function(t,e,i,n,r,o,s,a){for(var l,h,u=r,d=0,c=!!s&&vS(s,a);d0&&pS(l)?(h=fS(l),u=gS(t,e,l,h,u,o-1)-1):(mS(u+1),t[u]=l),u++),d++;return u},yS=gS,bS=Oe,_S=j,wS=Vn,kS=qa;En({target:"Array",proto:!0},{flatMap:function(t){var e,i=_S(this),n=wS(i);return bS(t),(e=kS(i,0)).length=yS(e,i,i,n,0,1,t,arguments.length>1?arguments[1]:void 0),e}});var xS=Jd("Array").flatMap,DS=ye,SS=xS,CS=Array.prototype,TS=function(t){var e=t.flatMap;return t===CS||DS(CS,t)&&e===CS.flatMap?SS:e},MS=n(TS),OS={exports:{}},ES=h((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),PS=h,AS=$t,IS=Dt,LS=ES,NS=Object.isExtensible,RS=PS((function(){NS(1)}))||LS?function(t){return!!AS(t)&&((!LS||"ArrayBuffer"!==IS(t))&&(!NS||NS(t)))}:NS,FS=!h((function(){return Object.isExtensible(Object.preventExtensions({}))})),jS=En,YS=m,HS=fi,zS=$t,BS=z,GS=Kt.f,WS=pl,VS=vl,US=RS,XS=FS,qS=!1,$S=U("meta"),ZS=0,KS=function(t){GS(t,$S,{value:{objectID:"O"+ZS++,weakData:{}}})},JS=OS.exports={enable:function(){JS.enable=function(){},qS=!0;var t=WS.f,e=YS([].splice),i={};i[$S]=1,t(i).length&&(WS.f=function(i){for(var n=t(i),r=0,o=n.length;r1?arguments[1]:void 0);e=e?e.next:i.first;)for(n(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!l(this,t)}}),_C(o,i?{get:function(t){var e=l(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),MC&&bC(o,"size",{configurable:!0,get:function(){return s(this).size}}),r},setStrong:function(t,e,i){var n=e+" Iterator",r=PC(e),o=PC(n);SC(t,e,(function(t,e){EC(this,{type:n,target:t,state:r(t),kind:e,last:void 0})}),(function(){for(var t=o(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?CC("keys"===e?i.key:"values"===e?i.value:[i.key,i.value],!1):(t.target=void 0,CC(void 0,!0))}),i?"entries":"values",!i,!0),TC(e)}};vC("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),AC);var IC=n(ce.Map);vC("Set",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),AC);var LC=n(ce.Set),NC=n(Ad),RC=n(zs),FC=kl,jC=Math.floor,YC=function(t,e){var i=t.length,n=jC(i/2);return i<8?HC(t,e):zC(t,YC(FC(t,0,n),e),YC(FC(t,n),e),e)},HC=function(t,e){for(var i,n,r=t.length,o=1;o0;)t[n]=t[--n];n!==o++&&(t[n]=i)}return t},zC=function(t,e,i,n){for(var r=e.length,o=i.length,s=0,a=0;s3)){if(oT)return!0;if(aT)return aT<603;var t,e,i,n,r="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(n=0;n<47;n++)lT.push({k:e+n,v:i})}for(lT.sort((function(t,e){return e.v-t.v})),n=0;ntT(i)?1:-1}}(t)),i=JC(r),n=0;n1?arguments[1]:void 0)}});var kT=Jd("Array").some,xT=ye,DT=kT,ST=Array.prototype,CT=function(t){var e=t.some;return t===ST||xT(ST,t)&&e===ST.some?DT:e},TT=n(CT),MT=Jd("Array").keys,OT=Pt,ET=z,PT=ye,AT=MT,IT=Array.prototype,LT={DOMTokenList:!0,NodeList:!0},NT=function(t){var e=t.keys;return t===IT||PT(IT,t)&&e===IT.keys||ET(LT,OT(t))?AT:e},RT=n(NT),FT=Jd("Array").values,jT=Pt,YT=z,HT=ye,zT=FT,BT=Array.prototype,GT={DOMTokenList:!0,NodeList:!0},WT=function(t){var e=t.values;return t===BT||HT(BT,t)&&e===BT.values||YT(GT,jT(t))?zT:e},VT=n(WT),UT=Jd("Array").entries,XT=Pt,qT=z,$T=ye,ZT=UT,KT=Array.prototype,JT={DOMTokenList:!0,NodeList:!0},QT=function(t){var e=t.entries;return t===KT||$T(KT,t)&&e===KT.entries||qT(JT,XT(t))?ZT:e},tM=n(QT),eM=n(Na),iM=En,nM=Ii,rM=bp,oM=Mw,sM=le,aM=$t,lM=Pr,hM=h,uM=ge("Reflect","construct"),dM=Object.prototype,cM=[].push,pM=hM((function(){function t(){}return!(uM((function(){}),[],t)instanceof t)})),fM=!hM((function(){uM((function(){}))})),mM=pM||fM;iM({target:"Reflect",stat:!0,forced:mM,sham:mM},{construct:function(t,e){oM(t),sM(e);var i=arguments.length<3?t:oM(arguments[2]);if(fM&&!pM)return uM(t,e,i);if(t===i){switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3])}var n=[null];return nM(cM,n,e),new(nM(rM,t,n))}var r=i.prototype,o=lM(aM(r)?r:dM),s=nM(t,o,e);return aM(s)?s:o}});var vM=n(ce.Reflect.construct),gM=n(ce.Object.getOwnPropertySymbols),yM={exports:{}},bM=En,_M=h,wM=$i,kM=Fi.f,xM=Zt;bM({target:"Object",stat:!0,forced:!xM||_M((function(){kM(1)})),sham:!xM},{getOwnPropertyDescriptor:function(t,e){return kM(wM(t),e)}});var DM=ce.Object,SM=yM.exports=function(t,e){return DM.getOwnPropertyDescriptor(t,e)};DM.getOwnPropertyDescriptor.sham&&(SM.sham=!0);var CM=n(yM.exports),TM=Uc,MM=$i,OM=Fi,EM=Ms;En({target:"Object",stat:!0,sham:!Zt},{getOwnPropertyDescriptors:function(t){for(var e,i,n=MM(t),r=OM.f,o=TM(n),s={},a=0;o.length>a;)void 0!==(i=r(n,e=o[a++]))&&EM(s,e,i);return s}});var PM=n(ce.Object.getOwnPropertyDescriptors),AM={exports:{}},IM=En,LM=Zt,NM=Fn.f;IM({target:"Object",stat:!0,forced:Object.defineProperties!==NM,sham:!LM},{defineProperties:NM});var RM=ce.Object,FM=AM.exports=function(t,e){return RM.defineProperties(t,e)};RM.defineProperties.sham&&(FM.sham=!0);var jM=n(AM.exports);let YM;const HM=new Uint8Array(16);function zM(){if(!YM&&(YM="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!YM))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return YM(HM)}const BM=[];for(let t=0;t<256;++t)BM.push((t+256).toString(16).slice(1));var GM,WM={randomUUID:"undefined"!=typeof crypto&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function VM(t,e,i){if(WM.randomUUID&&!e&&!t)return WM.randomUUID();const n=(t=t||{}).random||(t.rng||zM)();if(n[6]=15&n[6]|64,n[8]=63&n[8]|128,e){i=i||0;for(let t=0;t<16;++t)e[i+t]=n[t];return e}return function(t,e=0){return BM[t[e+0]]+BM[t[e+1]]+BM[t[e+2]]+BM[t[e+3]]+"-"+BM[t[e+4]]+BM[t[e+5]]+"-"+BM[t[e+6]]+BM[t[e+7]]+"-"+BM[t[e+8]]+BM[t[e+9]]+"-"+BM[t[e+10]]+BM[t[e+11]]+BM[t[e+12]]+BM[t[e+13]]+BM[t[e+14]]+BM[t[e+15]]}(n)}function UM(t,e){var i=rp(t);if(gM){var n=gM(t);e&&(n=mm(n).call(n,(function(e){return CM(t,e).enumerable}))),i.push.apply(i,n)}return i}function XM(t){for(var e=1;e=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function ZM(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);ithis.max&&this.flush(),null!=this._timeout&&(clearTimeout(this._timeout),this._timeout=null),this.queue.length>0&&"number"==typeof this.delay&&(this._timeout=Rv((function(){t.flush()}),this.delay))}},{key:"flush",value:function(){var t,e;Hp(t=_f(e=this._queue).call(e,0)).call(t,(function(t){t.fn.apply(t.context||t.fn,t.args||[])}))}}],[{key:"extend",value:function(e,i){var n=new t(i);if(void 0!==e.flush)throw new Error("Target object already has a property flush");e.flush=function(){n.flush()};var r=[{name:"flush",original:void 0}];if(i&&i.replace)for(var o=0;or&&(r=l,n=a)}return n}},{key:"min",value:function(t){var e=RC(this._pairs),i=e.next();if(i.done)return null;for(var n=i.value[1],r=t(i.value[1],i.value[0]);!(i=e.next()).done;){var o=Pc(i.value,2),s=o[0],a=o[1],l=t(a,s);lr?1:nr)&&(n=s,r=a)}}catch(t){o.e(t)}finally{o.f()}return n||null}},{key:"min",value:function(t){var e,i,n=null,r=null,o=$M(VT(e=this._data).call(e));try{for(o.s();!(i=o.n()).done;){var s=i.value,a=s[t];"number"==typeof a&&(null==r||a/g,PO=/"/g,AO=/"/g,IO=/&#([a-zA-Z0-9]*);?/gim,LO=/:?/gim,NO=/&newline;?/gim,RO=/((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a):/gi,FO=/e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi,jO=/u\s*r\s*l\s*\(.*/gi;function YO(t){return t.replace(PO,""")}function HO(t){return t.replace(AO,'"')}function zO(t){return t.replace(IO,(function(t,e){return"x"===e[0]||"X"===e[0]?String.fromCharCode(parseInt(e.substr(1),16)):String.fromCharCode(parseInt(e,10))}))}function BO(t){return t.replace(LO,":").replace(NO," ")}function GO(t){for(var e="",i=0,n=t.length;i0;e--){var i=t[e];if(" "!==i)return"="===i?e:-1}}function tE(t){return function(t){return'"'===t[0]&&'"'===t[t.length-1]||"'"===t[0]&&"'"===t[t.length-1]}(t)?t.substr(1,t.length-2):t}UO.parseTag=function(t,e,i){var n="",r=0,o=!1,s=!1,a=0,l=t.length,h="",u="";t:for(a=0;a"===d||a===l-1){n+=i(t.slice(r,o)),h=qO(u=t.slice(o,a+1)),n+=e(o,n.length,h,u,$O(u)),r=a+1,o=!1;continue}if('"'===d||"'"===d)for(var c=1,p=t.charAt(a-c);""===p.trim()||"="===p;){if("="===p){s=d;continue t}p=t.charAt(a-++c)}}else if(d===s){s=!1;continue}}return r";var m=function(t){var e=sE.spaceIndex(t);if(-1===e)return{html:"",closing:"/"===t[t.length-2]};var i="/"===(t=sE.trim(t.slice(e+1,-1)))[t.length-1];return i&&(t=sE.trim(t.slice(0,-1))),{html:t,closing:i}}(d),v=i[u],g=oE(m.html,(function(t,e){var i=-1!==sE.indexOf(v,t),n=o(u,t,e,i);return aE(n)?i?(e=a(u,t,e,h))?t+'="'+e+'"':t:aE(n=s(u,t,e,i))?void 0:n:n}));return d="<"+u,g&&(d+=" "+g),m.closing&&(d+=" /"),d+=">"}return aE(f=r(u,d,p))?l(d):f}),l);return u&&(d=u.remove(d)),d};var hE=lE;!function(t,e){var i=hO,n=UO,r=hE;function o(t,e){return new r(e).process(t)}(e=t.exports=o).filterXSS=o,e.FilterXSS=r,function(){for(var t in i)e[t]=i[t];for(var r in n)e[r]=n[r]}(),"undefined"!=typeof window&&(window.filterXSS=t.exports),"undefined"!=typeof self&&"undefined"!=typeof DedicatedWorkerGlobalScope&&self instanceof DedicatedWorkerGlobalScope&&(self.filterXSS=t.exports)}(lO,lO.exports);var uE=n(lO.exports);function dE(t,e){var i=rp(t);if(gM){var n=gM(t);e&&(n=mm(n).call(n,(function(e){return CM(t,e).enumerable}))),i.push.apply(i,n)}return i}function cE(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:{start:"Date",end:"Date"},l=t._idProp,h=new nO({fieldId:l}),u=ep(e=function(t){return new JM(t)}(t)).call(e,(function(t){var e;return cS(e=rp(t)).call(e,(function(e,i){return e[i]=vE(t[i],a[i]),e}),{})})).to(h);return u.all().start(),{add:function(){var e;return(e=t.getDataSet()).add.apply(e,arguments)},remove:function(){var e;return(e=t.getDataSet()).remove.apply(e,arguments)},update:function(){var e;return(e=t.getDataSet()).update.apply(e,arguments)},updateOnly:function(){var e;return(e=t.getDataSet()).updateOnly.apply(e,arguments)},clear:function(){var e;return(e=t.getDataSet()).clear.apply(e,arguments)},forEach:Tp(i=Hp(h)).call(i,h),get:Tp(n=h.get).call(n,h),getIds:Tp(r=h.getIds).call(r,h),off:Tp(o=h.off).call(o,h),on:Tp(s=h.on).call(s,h),get length(){return h.length},idProp:l,type:a,rawDS:t,coercedDS:h,dispose:function(){return u.stop()}}}var yE=function(t){var e=new uE.FilterXSS(t);return function(t){return e.process(t)}},bE=function(t){return t},_E=yE(),wE=cE(cE({},Wb),{},{convert:vE,setupXSSProtection:function(t){t&&(!0===t.disabled?(_E=bE,console.warn("You disabled XSS protection for vis-Timeline. I sure hope you know what you're doing!")):t.filterOptions&&(_E=yE(t.filterOptions)))}});eM(wE,"xss",{get:function(){return _E}});var kE=w,xE=h,DE=Lt,SE=Fm.trim,CE=Om,TE=m("".charAt),ME=kE.parseFloat,OE=kE.Symbol,EE=OE&&OE.iterator,PE=1/ME(CE+"-0")!=-1/0||EE&&!xE((function(){ME(Object(EE))}))?function(t){var e=SE(DE(t)),i=ME(e);return 0===i&&"-"===TE(e,0)?-0:i}:ME;En({global:!0,forced:parseFloat!==PE},{parseFloat:PE});var AE=n(ce.parseFloat),IE=function(){function t(e,i){Ma(this,t),this.options=null,this.props=null}return Yd(t,[{key:"setOptions",value:function(t){t&&wE.extend(this.options,t)}},{key:"redraw",value:function(){return!1}},{key:"destroy",value:function(){}},{key:"_isResized",value:function(){var t=this.props._previousWidth!==this.props.width||this.props._previousHeight!==this.props.height;return this.props._previousWidth=this.props.width,this.props._previousHeight=this.props.height,t}}]),t}(),LE=b,NE=Lt,RE=N,FE=RangeError;En({target:"String",proto:!0},{repeat:function(t){var e=NE(RE(this)),i="",n=LE(t);if(n<0||n===1/0)throw new FE("Wrong number of repetitions");for(;n>0;(n>>>=1)&&(e+=e))1&n&&(i+=e);return i}});var jE=Jd("String").repeat,YE=ye,HE=jE,zE=String.prototype,BE=function(t){var e=t.repeat;return"string"==typeof t||t===zE||YE(zE,t)&&e===zE.repeat?HE:e},GE=n(BE);function WE(t,e,i){if(i&&!qc(i))return WE(t,e,[i]);if(e.hiddenDates=[],i&&1==qc(i)){for(var n,r=0;r=4*o){var h=0,u=r.clone();switch(GE(i[s])){case"daily":a.day()!=l.day()&&(h=1),a.dayOfYear(n.dayOfYear()),a.year(n.year()),a.subtract(7,"days"),l.dayOfYear(n.dayOfYear()),l.year(n.year()),l.subtract(7-h,"days"),u.add(1,"weeks");break;case"weekly":var d=l.diff(a,"days"),c=a.day();a.date(n.date()),a.month(n.month()),a.year(n.year()),l=a.clone(),a.day(c),l.day(c),l.add(d,"days"),a.subtract(1,"weeks"),l.subtract(1,"weeks"),u.add(1,"weeks");break;case"monthly":a.month()!=l.month()&&(h=1),a.month(n.month()),a.year(n.year()),a.subtract(1,"months"),l.month(n.month()),l.year(n.year()),l.subtract(1,"months"),l.add(h,"months"),u.add(1,"months");break;case"yearly":a.year()!=l.year()&&(h=1),a.year(n.year()),a.subtract(1,"years"),l.year(n.year()),l.subtract(1,"years"),l.add(h,"years"),u.add(1,"years");break;default:return void console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:",GE(i[s]))}for(;a=i[r].start&&i[o].end<=i[r].end?i[o].remove=!0:i[o].start>=i[r].start&&i[o].start<=i[r].end?(i[r].end=i[o].end,i[o].remove=!0):i[o].end>=i[r].start&&i[o].end<=i[r].end&&(i[r].start=i[o].start,i[o].remove=!0));for(r=0;r=s&&rt.range.end){var a={start:t.range.start,end:e};return e=JE(t.options.moment,t.body.hiddenDates,a,e),n=t.range.conversion(i,o),(e.valueOf()-n.offset)*n.scale}return e=JE(t.options.moment,t.body.hiddenDates,t.range,e),n=t.range.conversion(i,o),(e.valueOf()-n.offset)*n.scale}function $E(t,e,i){if(0==t.body.hiddenDates.length){var n=t.range.conversion(i);return new Date(e/n.scale+n.offset)}var r=ZE(t.body.hiddenDates,t.range.start,t.range.end),o=(t.range.end-t.range.start-r)*e/i,s=tP(t.body.hiddenDates,t.range,o);return new Date(s+o+t.range.start)}function ZE(t,e,i){for(var n=0,r=0;r=e&&s=e&&s<=i&&(n+=s-o)}return n}function JE(t,e,i,n){return n=t(n).toDate().valueOf(),n-=QE(t,e,i,n)}function QE(t,e,i,n){var r=0;n=t(n).toDate().valueOf();for(var o=0;o=i.start&&a=a&&(r+=a-s)}return r}function tP(t,e,i){for(var n=0,r=0,o=e.start,s=0;s=e.start&&l=i)break;n+=l-a}}return n}function eP(t,e,i,n){var r=iP(e,t);return 1==r.hidden?i<0?1==n?r.startDate-(r.endDate-e)-1:r.startDate-1:1==n?r.endDate+(e-r.startDate)+1:r.endDate+1:e}function iP(t,e){for(var i=0;i=n&&t1e3&&(i=1e3),t.body.dom.rollingModeBtn.style.visibility="hidden",t.currentTimeTimer=Rv(e,i)}()}},{key:"stopRolling",value:function(){void 0!==this.currentTimeTimer&&(clearTimeout(this.currentTimeTimer),this.rolling=!1,this.body.dom.rollingModeBtn.style.visibility="visible")}},{key:"setRange",value:function(t,e,i,n,r){i||(i={}),!0!==i.byUser&&(i.byUser=!1);var o=this,s=null!=t?wE.convert(t,"Date").valueOf():null,a=null!=e?wE.convert(e,"Date").valueOf():null;if(this._cancelAnimation(),this.millisecondsPerPixelCache=void 0,i.animation){var l,h=this.start,u=this.end,d="object"===Nd(i.animation)&&"duration"in i.animation?i.animation.duration:500,c="object"===Nd(i.animation)&&"easingFunction"in i.animation?i.animation.easingFunction:"easeInOutQuad",p=wE.easingFunctions[c];if(!p)throw new Error(Yc(l="Unknown easing function ".concat(vv(c),". Choose from: ")).call(l,rp(wE.easingFunctions).join(", ")));var f=lp(),m=!1;return function t(){if(!o.props.touch.dragging){var e=lp()-f,l=p(e/d),c=e>d,g=c||null===s?s:h+(s-h)*l,y=c||null===a?a:u+(a-u)*l;v=o._applyRange(g,y),VE(o.options.moment,o.body,o.options.hiddenDates),m=m||v;var b={start:new Date(o.start),end:new Date(o.end),byUser:i.byUser,event:i.event};if(r&&r(l,v,c),v&&o.body.emitter.emit("rangechange",b),c){if(m&&(o.body.emitter.emit("rangechanged",b),n))return n()}else o.animationTimer=Rv(t,20)}}()}var v=this._applyRange(s,a);if(VE(this.options.moment,this.body,this.options.hiddenDates),v){var g={start:new Date(this.start),end:new Date(this.end),byUser:i.byUser,event:i.event};if(this.body.emitter.emit("rangechange",g),clearTimeout(o.timeoutID),o.timeoutID=Rv((function(){o.body.emitter.emit("rangechanged",g)}),200),n)return n()}}},{key:"getMillisecondsPerPixel",value:function(){return void 0===this.millisecondsPerPixelCache&&(this.millisecondsPerPixelCache=(this.end-this.start)/this.body.dom.center.clientWidth),this.millisecondsPerPixelCache}},{key:"_cancelAnimation",value:function(){this.animationTimer&&(clearTimeout(this.animationTimer),this.animationTimer=null)}},{key:"_applyRange",value:function(t,e){var i,n=null!=t?wE.convert(t,"Date").valueOf():this.start,r=null!=e?wE.convert(e,"Date").valueOf():this.end,o=null!=this.options.max?wE.convert(this.options.max,"Date").valueOf():null,s=null!=this.options.min?wE.convert(this.options.min,"Date").valueOf():null;if(isNaN(n)||null===n)throw new Error('Invalid start "'.concat(t,'"'));if(isNaN(r)||null===r)throw new Error('Invalid end "'.concat(e,'"'));if(ro&&(r=o)),null!==o&&r>o&&(n-=i=r-o,r-=i,null!=s&&n=this.start-.5&&r<=this.end?(n=this.start,r=this.end):(n-=(i=a-(r-n))/2,r+=i/2)}}if(null!==this.options.zoomMax){var l=AE(this.options.zoomMax);l<0&&(l=0),r-n>l&&(this.end-this.start===l&&nthis.end?(n=this.start,r=this.end):(n+=(i=r-n-l)/2,r-=i/2))}var h=this.start!=n||this.end!=r;return n>=this.start&&n<=this.end||r>=this.start&&r<=this.end||this.start>=n&&this.start<=r||this.end>=n&&this.end<=r||this.body.emitter.emit("checkRangedItems"),this.start=n,this.end=r,h}},{key:"getRange",value:function(){return{start:this.start,end:this.end}}},{key:"conversion",value:function(t,e){return i.conversion(this.start,this.end,t,e)}},{key:"_onDragStart",value:function(t){this.deltaDifference=0,this.previousDelta=0,this.options.moveable&&this._isInsideRange(t)&&this.props.touch.allowDragging&&(this.stopRolling(),this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.dragging=!0,this.body.dom.root&&(this.body.dom.root.style.cursor="move"))}},{key:"_onDrag",value:function(t){if(t&&this.props.touch.dragging&&this.options.moveable&&this.props.touch.allowDragging){var e=this.options.direction;sP(e);var i="horizontal"==e?t.deltaX:t.deltaY;i-=this.deltaDifference;var n=this.props.touch.end-this.props.touch.start;n-=ZE(this.body.hiddenDates,this.start,this.end);var r,o="horizontal"==e?this.body.domProps.center.width:this.body.domProps.center.height;r=this.options.rtl?i/o*n:-i/o*n;var s=this.props.touch.start+r,a=this.props.touch.end+r,l=eP(this.body.hiddenDates,s,this.previousDelta-i,!0),h=eP(this.body.hiddenDates,a,this.previousDelta-i,!0);if(l!=s||h!=a)return this.deltaDifference+=i,this.props.touch.start=l,this.props.touch.end=h,void this._onDrag(t);this.previousDelta=i,this._applyRange(s,a);var u=new Date(this.start),d=new Date(this.end);this.body.emitter.emit("rangechange",{start:u,end:d,byUser:!0,event:t}),this.body.emitter.emit("panmove")}}},{key:"_onDragEnd",value:function(t){this.props.touch.dragging&&this.options.moveable&&this.props.touch.allowDragging&&(this.props.touch.dragging=!1,this.body.dom.root&&(this.body.dom.root.style.cursor="auto"),this.body.emitter.emit("rangechanged",{start:new Date(this.start),end:new Date(this.end),byUser:!0,event:t}))}},{key:"_onMouseWheel",value:function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail?e=-t.detail/3:t.deltaY&&(e=-t.deltaY/3),!(this.options.zoomKey&&!t[this.options.zoomKey]&&this.options.zoomable||!this.options.zoomable&&this.options.moveable)&&this.options.zoomable&&this.options.moveable&&this._isInsideRange(t)&&e){var i,n,r=this.options.zoomFriction||5;if(i=e<0?1-e/r:1/(1+e/r),this.rolling){var o=this.options.rollingMode&&this.options.rollingMode.offset||.5;n=this.start+(this.end-this.start)*o}else{var s=this.getPointer({x:t.clientX,y:t.clientY},this.body.dom.center);n=this._pointerToDate(s)}this.zoom(i,n,e,t),t.preventDefault()}}},{key:"_onTouch",value:function(t){this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.allowDragging=!0,this.props.touch.center=null,this.props.touch.centerDate=null,this.scaleOffset=0,this.deltaDifference=0,wE.preventDefault(t)}},{key:"_onPinch",value:function(t){if(this.options.zoomable&&this.options.moveable){wE.preventDefault(t),this.props.touch.allowDragging=!1,this.props.touch.center||(this.props.touch.center=this.getPointer(t.center,this.body.dom.center),this.props.touch.centerDate=this._pointerToDate(this.props.touch.center)),this.stopRolling();var e=1/(t.scale+this.scaleOffset),i=this.props.touch.centerDate,n=ZE(this.body.hiddenDates,this.start,this.end),r=QE(this.options.moment,this.body.hiddenDates,this,i),o=n-r,s=i-r+(this.props.touch.start-(i-r))*e,a=i+o+(this.props.touch.end-(i+o))*e;this.startToFront=1-e<=0,this.endToFront=e-1<=0;var l=eP(this.body.hiddenDates,s,1-e,!0),h=eP(this.body.hiddenDates,a,e-1,!0);l==s&&h==a||(this.props.touch.start=l,this.props.touch.end=h,this.scaleOffset=1-t.scale,s=l,a=h);var u={animation:!1,byUser:!0,event:t};this.setRange(s,a,u),this.startToFront=!1,this.endToFront=!0}}},{key:"_isInsideRange",value:function(t){var e=t.center?t.center.x:t.clientX,i=this.body.dom.centerContainer.getBoundingClientRect(),n=this.options.rtl?e-i.left:i.right-e,r=this.body.util.toTime(n);return r>=this.start&&r<=this.end}},{key:"_pointerToDate",value:function(t){var e,i=this.options.direction;if(sP(i),"horizontal"==i)return this.body.util.toTime(t.x).valueOf();var n=this.body.domProps.center.height;return e=this.conversion(n),t.y/e.scale+e.offset}},{key:"getPointer",value:function(t,e){var i=e.getBoundingClientRect();return this.options.rtl?{x:i.right-t.x,y:t.y-i.top}:{x:t.x-i.left,y:t.y-i.top}}},{key:"zoom",value:function(t,e,i,n){null==e&&(e=(this.start+this.end)/2);var r=ZE(this.body.hiddenDates,this.start,this.end),o=QE(this.options.moment,this.body.hiddenDates,this,e),s=r-o,a=e-o+(this.start-(e-o))*t,l=e+s+(this.end-(e+s))*t;this.startToFront=!(i>0),this.endToFront=!(-i>0);var h=eP(this.body.hiddenDates,a,i,!0),u=eP(this.body.hiddenDates,l,-i,!0);h==a&&u==l||(a=h,l=u);var d={animation:!1,byUser:!0,event:n};this.setRange(a,l,d),this.startToFront=!1,this.endToFront=!0}},{key:"move",value:function(t){var e=this.end-this.start,i=this.start+e*t,n=this.end+e*t;this.start=i,this.end=n}},{key:"moveTo",value:function(t){var e=(this.start+this.end)/2-t,i=this.start-e,n=this.end-e;this.setRange(i,n,{animation:!1,byUser:!0,event:null})}},{key:"destroy",value:function(){this.stopRolling()}}],[{key:"conversion",value:function(t,e,i,n){return void 0===n&&(n=0),0!=i&&e-t!=0?{offset:t,scale:i/(e-t-n)}:{offset:0,scale:1}}}]),i}(IE);function sP(t){if("horizontal"!=t&&"vertical"!=t)throw new TypeError('Unknown direction "'.concat(t,'". Choose "horizontal" or "vertical".'))}var aP,lP=n(ce.setInterval),hP=null;"undefined"!=typeof window?aP=function t(e,i){var n=i||{preventDefault:!1};if(e.Manager){var r=e,o=function(e,i){var o=Object.create(n);return i&&r.assign(o,i),t(new r(e,o),o)};return r.assign(o,r),o.Manager=function(e,i){var o=Object.create(n);return i&&r.assign(o,i),t(new r.Manager(e,o),o)},o}var s=Object.create(e),a=e.element;function l(t){return t.match(/[^ ]+/g)}function h(t){if("hammer.input"!==t.type){if(t.srcEvent._handled||(t.srcEvent._handled={}),t.srcEvent._handled[t.type])return;t.srcEvent._handled[t.type]=!0}var e=!1;t.stopPropagation=function(){e=!0};var i=t.srcEvent.stopPropagation.bind(t.srcEvent);"function"==typeof i&&(t.srcEvent.stopPropagation=function(){i(),t.stopPropagation()}),t.firstTarget=hP;for(var n=hP;n&&!e;){var r=n.hammer;if(r)for(var o,s=0;s0?s._handlers[t]=n:(e.off(t,h),delete s._handlers[t]))})),s},s.emit=function(t,i){hP=i.target,e.emit(t,i)},s.destroy=function(){var t=e.element.hammer,i=t.indexOf(s);-1!==i&&t.splice(i,1),t.length||delete e.element.hammer,s._handlers={},e.destroy()},s}(window.Hammer||Wy,{preventDefault:"mouse"}):aP=function(){return function(){var t=function(){};return{on:t,off:t,destroy:t,emit:t,get:function(e){return{set:t}}}}()};var uP=aP;function dP(t,e){e.inputHandler=function(t){t.isFirst&&e(t)},t.on("hammer.input",e.inputHandler)}var cP=function(){function t(e,i,n,r,o){Ma(this,t),this.moment=o&&o.moment||sO,this.options=o||{},this.current=this.moment(),this._start=this.moment(),this._end=this.moment(),this.autoScale=!0,this.scale="day",this.step=1,this.setRange(e,i,n),this.switchedDay=!1,this.switchedMonth=!1,this.switchedYear=!1,qc(r)?this.hiddenDates=r:this.hiddenDates=null!=r?[r]:[],this.format=t.FORMAT}return Yd(t,[{key:"setMoment",value:function(t){this.moment=t,this.current=this.moment(this.current.valueOf()),this._start=this.moment(this._start.valueOf()),this._end=this.moment(this._end.valueOf())}},{key:"setFormat",value:function(e){var i=wE.deepExtend({},t.FORMAT);this.format=wE.deepExtend(i,e)}},{key:"setRange",value:function(t,e,i){if(!(t instanceof Date&&e instanceof Date))throw"No legal start or end date in method setRange";this._start=null!=t?this.moment(t.valueOf()):lp(),this._end=null!=e?this.moment(e.valueOf()):lp(),this.autoScale&&this.setMinimumStep(i)}},{key:"start",value:function(){this.current=this._start.clone(),this.roundToMinor()}},{key:"roundToMinor",value:function(){switch("week"==this.scale&&this.current.weekday(0),this.scale){case"year":this.current.year(this.step*Math.floor(this.current.year()/this.step)),this.current.month(0);case"month":this.current.date(1);case"week":case"day":case"weekday":this.current.hours(0);case"hour":this.current.minutes(0);case"minute":this.current.seconds(0);case"second":this.current.milliseconds(0)}if(1!=this.step){var t=this.current.clone();switch(this.scale){case"millisecond":this.current.subtract(this.current.milliseconds()%this.step,"milliseconds");break;case"second":this.current.subtract(this.current.seconds()%this.step,"seconds");break;case"minute":this.current.subtract(this.current.minutes()%this.step,"minutes");break;case"hour":this.current.subtract(this.current.hours()%this.step,"hours");break;case"weekday":case"day":this.current.subtract((this.current.date()-1)%this.step,"day");break;case"week":this.current.subtract(this.current.week()%this.step,"week");break;case"month":this.current.subtract(this.current.month()%this.step,"month");break;case"year":this.current.subtract(this.current.year()%this.step,"year")}t.isSame(this.current)||(this.current=this.moment(eP(this.hiddenDates,this.current.valueOf(),-1,!0)))}}},{key:"hasNext",value:function(){return this.current.valueOf()<=this._end.valueOf()}},{key:"next",value:function(){var t=this.current.valueOf();switch(this.scale){case"millisecond":this.current.add(this.step,"millisecond");break;case"second":this.current.add(this.step,"second");break;case"minute":this.current.add(this.step,"minute");break;case"hour":this.current.add(this.step,"hour"),this.current.month()<6?this.current.subtract(this.current.hours()%this.step,"hour"):this.current.hours()%this.step!=0&&this.current.add(this.step-this.current.hours()%this.step,"hour");break;case"weekday":case"day":this.current.add(this.step,"day");break;case"week":if(0!==this.current.weekday())this.current.weekday(0),this.current.add(this.step,"week");else if(!1===this.options.showMajorLabels)this.current.add(this.step,"week");else{var e=this.current.clone();e.add(1,"week"),e.isSame(this.current,"month")?this.current.add(this.step,"week"):(this.current.add(this.step,"week"),this.current.date(1))}break;case"month":this.current.add(this.step,"month");break;case"year":this.current.add(this.step,"year")}if(1!=this.step)switch(this.scale){case"millisecond":this.current.milliseconds()>0&&this.current.milliseconds()0&&this.current.seconds()0&&this.current.minutes()0&&this.current.hours()0?t.step:1,this.autoScale=!1)}},{key:"setAutoScale",value:function(t){this.autoScale=t}},{key:"setMinimumStep",value:function(t){if(null!=t){var e=31104e6,i=2592e6,n=864e5,r=36e5,o=6e4,s=1e3;1e3*e>t&&(this.scale="year",this.step=1e3),500*e>t&&(this.scale="year",this.step=500),100*e>t&&(this.scale="year",this.step=100),50*e>t&&(this.scale="year",this.step=50),10*e>t&&(this.scale="year",this.step=10),5*e>t&&(this.scale="year",this.step=5),e>t&&(this.scale="year",this.step=1),7776e6>t&&(this.scale="month",this.step=3),i>t&&(this.scale="month",this.step=1),6048e5>t&&this.options.showWeekScale&&(this.scale="week",this.step=1),1728e5>t&&(this.scale="day",this.step=2),n>t&&(this.scale="day",this.step=1),432e5>t&&(this.scale="weekday",this.step=1),144e5>t&&(this.scale="hour",this.step=4),r>t&&(this.scale="hour",this.step=1),9e5>t&&(this.scale="minute",this.step=15),6e5>t&&(this.scale="minute",this.step=10),3e5>t&&(this.scale="minute",this.step=5),o>t&&(this.scale="minute",this.step=1),15e3>t&&(this.scale="second",this.step=15),1e4>t&&(this.scale="second",this.step=10),5e3>t&&(this.scale="second",this.step=5),s>t&&(this.scale="second",this.step=1),200>t&&(this.scale="millisecond",this.step=200),100>t&&(this.scale="millisecond",this.step=100),50>t&&(this.scale="millisecond",this.step=50),10>t&&(this.scale="millisecond",this.step=10),5>t&&(this.scale="millisecond",this.step=5),1>t&&(this.scale="millisecond",this.step=1)}}},{key:"isMajor",value:function(){if(1==this.switchedYear)switch(this.scale){case"year":case"month":case"week":case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedMonth)switch(this.scale){case"week":case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedDay)switch(this.scale){case"millisecond":case"second":case"minute":case"hour":return!0;default:return!1}var t=this.moment(this.current);switch(this.scale){case"millisecond":return 0==t.milliseconds();case"second":return 0==t.seconds();case"minute":return 0==t.hours()&&0==t.minutes();case"hour":return 0==t.hours();case"weekday":case"day":return this.options.showWeekScale?1==t.isoWeekday():1==t.date();case"week":return 1==t.date();case"month":return 0==t.month();default:return!1}}},{key:"getLabelMinor",value:function(t){if(null==t&&(t=this.current),t instanceof Date&&(t=this.moment(t)),"function"==typeof this.format.minorLabels)return this.format.minorLabels(t,this.scale,this.step);var e=this.format.minorLabels[this.scale];return"week"===this.scale&&1===t.date()&&0!==t.weekday()?"":e&&e.length>0?this.moment(t).format(e):""}},{key:"getLabelMajor",value:function(t){if(null==t&&(t=this.current),t instanceof Date&&(t=this.moment(t)),"function"==typeof this.format.majorLabels)return this.format.majorLabels(t,this.scale,this.step);var e=this.format.majorLabels[this.scale];return e&&e.length>0?this.moment(t).format(e):""}},{key:"getClassName",value:function(){var t,e=this.moment,i=this.moment(this.current),n=i.locale?i.locale("en"):i.lang("en"),r=this.step,o=[];function s(t){return t/r%2==0?" vis-even":" vis-odd"}function a(t){return t.isSame(lp(),"day")?" vis-today":t.isSame(e().add(1,"day"),"day")?" vis-tomorrow":t.isSame(e().add(-1,"day"),"day")?" vis-yesterday":""}function l(t){return t.isSame(lp(),"week")?" vis-current-week":""}function h(t){return t.isSame(lp(),"month")?" vis-current-month":""}switch(this.scale){case"millisecond":o.push(a(n)),o.push(s(n.milliseconds()));break;case"second":o.push(a(n)),o.push(s(n.seconds()));break;case"minute":o.push(a(n)),o.push(s(n.minutes()));break;case"hour":o.push(Yc(t="vis-h".concat(n.hours())).call(t,4==this.step?"-h"+(n.hours()+4):"")),o.push(a(n)),o.push(s(n.hours()));break;case"weekday":o.push("vis-".concat(n.format("dddd").toLowerCase())),o.push(a(n)),o.push(l(n)),o.push(s(n.date()));break;case"day":o.push("vis-day".concat(n.date())),o.push("vis-".concat(n.format("MMMM").toLowerCase())),o.push(a(n)),o.push(h(n)),o.push(this.step<=2?a(n):""),o.push(this.step<=2?"vis-".concat(n.format("dddd").toLowerCase()):""),o.push(s(n.date()-1));break;case"week":o.push("vis-week".concat(n.format("w"))),o.push(l(n)),o.push(s(n.week()));break;case"month":o.push("vis-".concat(n.format("MMMM").toLowerCase())),o.push(h(n)),o.push(s(n.month()));break;case"year":o.push("vis-year".concat(n.year())),o.push(function(t){return t.isSame(lp(),"year")?" vis-current-year":""}(n)),o.push(s(n.year()))}return mm(o).call(o,String).join(" ")}}],[{key:"snap",value:function(t,e,i){var n=sO(t);if("year"==e){var r=n.year()+Math.round(n.month()/12);n.year(Math.round(r/i)*i),n.month(0),n.date(0),n.hours(0),n.minutes(0),n.seconds(0),n.milliseconds(0)}else if("month"==e)n.date()>15?(n.date(1),n.add(1,"month")):n.date(1),n.hours(0),n.minutes(0),n.seconds(0),n.milliseconds(0);else if("week"==e)n.weekday()>2?(n.weekday(0),n.add(1,"week")):n.weekday(0),n.hours(0),n.minutes(0),n.seconds(0),n.milliseconds(0);else if("day"==e){switch(i){case 5:case 2:n.hours(24*Math.round(n.hours()/24));break;default:n.hours(12*Math.round(n.hours()/12))}n.minutes(0),n.seconds(0),n.milliseconds(0)}else if("weekday"==e){switch(i){case 5:case 2:n.hours(12*Math.round(n.hours()/12));break;default:n.hours(6*Math.round(n.hours()/6))}n.minutes(0),n.seconds(0),n.milliseconds(0)}else if("hour"==e){if(4===i)n.minutes(60*Math.round(n.minutes()/60));else n.minutes(30*Math.round(n.minutes()/30));n.seconds(0),n.milliseconds(0)}else if("minute"==e){switch(i){case 15:case 10:n.minutes(5*Math.round(n.minutes()/5)),n.seconds(0);break;case 5:n.seconds(60*Math.round(n.seconds()/60));break;default:n.seconds(30*Math.round(n.seconds()/30))}n.milliseconds(0)}else if("second"==e)switch(i){case 15:case 10:n.seconds(5*Math.round(n.seconds()/5)),n.milliseconds(0);break;case 5:n.milliseconds(1e3*Math.round(n.milliseconds()/1e3));break;default:n.milliseconds(500*Math.round(n.milliseconds()/500))}else if("millisecond"==e){var o=i>5?i/2:1;n.milliseconds(Math.round(n.milliseconds()/o)*o)}return n}}]),t}();function pP(t,e){void 0===e&&(e={});var i=e.insertAt;if(t&&"undefined"!=typeof document){var n=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===i&&n.firstChild?n.insertBefore(r,n.firstChild):n.appendChild(r),r.styleSheet?r.styleSheet.cssText=t:r.appendChild(document.createTextNode(t))}}cP.FORMAT={minorLabels:{millisecond:"SSS",second:"s",minute:"HH:mm",hour:"HH:mm",weekday:"ddd D",day:"D",week:"w",month:"MMM",year:"YYYY"},majorLabels:{millisecond:"HH:mm:ss",second:"D MMMM HH:mm",minute:"ddd D MMMM",hour:"ddd D MMMM",weekday:"MMMM YYYY",day:"MMMM YYYY",week:"MMMM YYYY",month:"YYYY",year:""}};function fP(t){var e=function(){if("undefined"==typeof Reflect||!vM)return!1;if(vM.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(vM(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=d_(t);if(e){var r=d_(this).constructor;i=vM(n,arguments,r)}else i=n.apply(this,arguments);return l_(this,i)}}pP(".vis-time-axis{overflow:hidden;position:relative}.vis-time-axis.vis-foreground{left:0;top:0;width:100%}.vis-time-axis.vis-background{height:100%;left:0;position:absolute;top:0;width:100%}.vis-time-axis .vis-text{box-sizing:border-box;color:#4d4d4d;overflow:hidden;padding:3px;position:absolute;white-space:nowrap}.vis-time-axis .vis-text.vis-measure{margin-left:0;margin-right:0;padding-left:0;padding-right:0;position:absolute;visibility:hidden}.vis-time-axis .vis-grid.vis-vertical{border-left:1px solid;position:absolute}.vis-time-axis .vis-grid.vis-vertical-rtl{border-right:1px solid;position:absolute}.vis-time-axis .vis-grid.vis-minor{border-color:#e5e5e5}.vis-time-axis .vis-grid.vis-major{border-color:#bfbfbf}");var mP=function(t){a_(i,t);var e=fP(i);function i(t,n){var r;return Ma(this,i),(r=e.call(this)).dom={foreground:null,lines:[],majorTexts:[],minorTexts:[],redundant:{lines:[],majorTexts:[],minorTexts:[]}},r.props={range:{start:0,end:0,minimumStep:0},lineTop:0},r.defaultOptions={orientation:{axis:"bottom"},showMinorLabels:!0,showMajorLabels:!0,showWeekScale:!1,maxMinorChars:7,format:wE.extend({},cP.FORMAT),moment:sO,timeAxis:null},r.options=wE.extend({},r.defaultOptions),r.body=t,r._create(),r.setOptions(n),r}return Yd(i,[{key:"setOptions",value:function(t){t&&(wE.selectiveExtend(["showMinorLabels","showMajorLabels","showWeekScale","maxMinorChars","hiddenDates","timeAxis","moment","rtl"],this.options,t),wE.selectiveDeepExtend(["format"],this.options,t),"orientation"in t&&("string"==typeof t.orientation?this.options.orientation.axis=t.orientation:"object"===Nd(t.orientation)&&"axis"in t.orientation&&(this.options.orientation.axis=t.orientation.axis)),"locale"in t&&("function"==typeof sO.locale?sO.locale(t.locale):sO.lang(t.locale)))}},{key:"_create",value:function(){this.dom.foreground=document.createElement("div"),this.dom.background=document.createElement("div"),this.dom.foreground.className="vis-time-axis vis-foreground",this.dom.background.className="vis-time-axis vis-background"}},{key:"destroy",value:function(){this.dom.foreground.parentNode&&this.dom.foreground.parentNode.removeChild(this.dom.foreground),this.dom.background.parentNode&&this.dom.background.parentNode.removeChild(this.dom.background),this.body=null}},{key:"redraw",value:function(){var t=this.props,e=this.dom.foreground,i=this.dom.background,n="top"==this.options.orientation.axis?this.body.dom.top:this.body.dom.bottom,r=e.parentNode!==n;this._calculateCharSize();var o=this.options.showMinorLabels&&"none"!==this.options.orientation.axis,s=this.options.showMajorLabels&&"none"!==this.options.orientation.axis;t.minorLabelHeight=o?t.minorCharHeight:0,t.majorLabelHeight=s?t.majorCharHeight:0,t.height=t.minorLabelHeight+t.majorLabelHeight,t.width=e.offsetWidth,t.minorLineHeight=this.body.domProps.root.height-t.majorLabelHeight-("top"==this.options.orientation.axis?this.body.domProps.bottom.height:this.body.domProps.top.height),t.minorLineWidth=1,t.majorLineHeight=t.minorLineHeight+t.majorLabelHeight,t.majorLineWidth=1;var a=e.nextSibling,l=i.nextSibling;return e.parentNode&&e.parentNode.removeChild(e),i.parentNode&&i.parentNode.removeChild(i),e.style.height="".concat(this.props.height,"px"),this._repaintLabels(),a?n.insertBefore(e,a):n.appendChild(e),l?this.body.dom.backgroundVertical.insertBefore(i,l):this.body.dom.backgroundVertical.appendChild(i),this._isResized()||r}},{key:"_repaintLabels",value:function(){var t=this.options.orientation.axis,e=wE.convert(this.body.range.start,"Number"),i=wE.convert(this.body.range.end,"Number"),n=this.body.util.toTime((this.props.minorCharWidth||10)*this.options.maxMinorChars).valueOf(),r=n-QE(this.options.moment,this.body.hiddenDates,this.body.range,n);r-=this.body.util.toTime(0).valueOf();var o=new cP(new Date(e),new Date(i),r,this.body.hiddenDates,this.options);o.setMoment(this.options.moment),this.options.format&&o.setFormat(this.options.format),this.options.timeAxis&&o.setScale(this.options.timeAxis),this.step=o;var s,a,l,h,u,d,c=this.dom;c.redundant.lines=c.lines,c.redundant.majorTexts=c.majorTexts,c.redundant.minorTexts=c.minorTexts,c.lines=[],c.majorTexts=[],c.minorTexts=[];var p,f,m,v=0,g=void 0,y=0,b=1e3;for(o.start(),a=o.getCurrent(),h=this.body.util.toScreen(a);o.hasNext()&&y=.4*p;if(this.options.showMinorLabels&&d){var _=this._repaintMinorText(l,o.getLabelMinor(s),t,m);_.style.width="".concat(v,"px")}u&&this.options.showMajorLabels?(l>0&&(null==g&&(g=l),_=this._repaintMajorText(l,o.getLabelMajor(s),t,m)),f=this._repaintMajorLine(l,v,t,m)):d?f=this._repaintMinorLine(l,v,t,m):f&&(f.style.width="".concat(Zm(f.style.width)+v,"px"))}if(y!==b||vP||(console.warn("Something is wrong with the Timeline scale. Limited drawing of grid lines to ".concat(b," lines.")),vP=!0),this.options.showMajorLabels){var w=this.body.util.toTime(0),k=o.getLabelMajor(w),x=k.length*(this.props.majorCharWidth||10)+10;(null==g||x.vis-custom-time-marker{background-color:inherit;color:#fff;cursor:auto;font-size:12px;padding:3px 5px;top:0;white-space:nowrap;z-index:inherit}");var NP=function(t){a_(i,t);var e=LP(i);function i(t,n){var r,o;Ma(this,i),(o=e.call(this)).body=t,o.defaultOptions={moment:sO,locales:IP,locale:"en",id:void 0,title:void 0},o.options=wE.extend({},o.defaultOptions),o.setOptions(n),o.options.locales=wE.extend({},IP,o.options.locales);var s=o.defaultOptions.locales[o.defaultOptions.locale];return Hp(r=rp(o.options.locales)).call(r,(function(t){o.options.locales[t]=wE.extend({},s,o.options.locales[t])})),n&&null!=n.time?o.customTime=n.time:o.customTime=new Date,o.eventParams={},o._create(),o}return Yd(i,[{key:"setOptions",value:function(t){t&&wE.selectiveExtend(["moment","locale","locales","id","title","rtl","snap"],this.options,t)}},{key:"_create",value:function(){var t,e,i,n=document.createElement("div");n["custom-time"]=this,n.className="vis-custom-time ".concat(this.options.id||""),n.style.position="absolute",n.style.top="0px",n.style.height="100%",this.bar=n;var r=document.createElement("div");function o(t){this.body.range._onMouseWheel(t)}r.style.position="relative",r.style.top="0px",this.options.rtl?r.style.right="-10px":r.style.left="-10px",r.style.height="100%",r.style.width="20px",r.addEventListener?(r.addEventListener("mousewheel",Tp(o).call(o,this),!1),r.addEventListener("DOMMouseScroll",Tp(o).call(o,this),!1)):r.attachEvent("onmousewheel",Tp(o).call(o,this)),n.appendChild(r),this.hammer=new uP(r),this.hammer.on("panstart",Tp(t=this._onDragStart).call(t,this)),this.hammer.on("panmove",Tp(e=this._onDrag).call(e,this)),this.hammer.on("panend",Tp(i=this._onDragEnd).call(i,this)),this.hammer.get("pan").set({threshold:5,direction:uP.DIRECTION_ALL}),this.hammer.get("press").set({time:1e4})}},{key:"destroy",value:function(){this.hide(),this.hammer.destroy(),this.hammer=null,this.body=null}},{key:"redraw",value:function(){var t=this.body.dom.backgroundVertical;this.bar.parentNode!=t&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),t.appendChild(this.bar));var e=this.body.util.toScreen(this.customTime),i=this.options.locales[this.options.locale];i||(this.warned||(console.warn("WARNING: options.locales['".concat(this.options.locale,"'] not found. See https://visjs.github.io/vis-timeline/docs/timeline/#Localization")),this.warned=!0),i=this.options.locales.en);var n,r=this.options.title;void 0===r?r=(r=Yc(n="".concat(i.time,": ")).call(n,this.options.moment(this.customTime).format("dddd, MMMM Do YYYY, H:mm:ss"))).charAt(0).toUpperCase()+r.substring(1):"function"==typeof r&&(r=r.call(this,this.customTime));return this.options.rtl?this.bar.style.right="".concat(e,"px"):this.bar.style.left="".concat(e,"px"),this.bar.title=r,!1}},{key:"hide",value:function(){this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar)}},{key:"setCustomTime",value:function(t){this.customTime=wE.convert(t,"Date"),this.redraw()}},{key:"getCustomTime",value:function(){return new Date(this.customTime.valueOf())}},{key:"setCustomMarker",value:function(t,e){var i,n;(this.marker&&this.bar.removeChild(this.marker),this.marker=document.createElement("div"),this.marker.className="vis-custom-time-marker",this.marker.innerHTML=wE.xss(t),this.marker.style.position="absolute",e)&&(this.marker.setAttribute("contenteditable","true"),this.marker.addEventListener("pointerdown",(function(){this.marker.focus()})),this.marker.addEventListener("input",Tp(i=this._onMarkerChange).call(i,this)),this.marker.title=t,this.marker.addEventListener("blur",Tp(n=function(t){this.title!=t.target.innerHTML&&(this._onMarkerChanged(t),this.title=t.target.innerHTML)}).call(n,this)));this.bar.appendChild(this.marker)}},{key:"setCustomTitle",value:function(t){this.options.title=t}},{key:"_onDragStart",value:function(t){this.eventParams.dragging=!0,this.eventParams.customTime=this.customTime,t.stopPropagation()}},{key:"_onDrag",value:function(t){if(this.eventParams.dragging){var e=this.options.rtl?-1*t.deltaX:t.deltaX,i=this.body.util.toScreen(this.eventParams.customTime)+e,n=this.body.util.toTime(i),r=this.body.util.getScale(),o=this.body.util.getStep(),s=this.options.snap,a=s?s(n,r,o):n;this.setCustomTime(a),this.body.emitter.emit("timechange",{id:this.options.id,time:new Date(this.customTime.valueOf()),event:t}),t.stopPropagation()}}},{key:"_onDragEnd",value:function(t){this.eventParams.dragging&&(this.body.emitter.emit("timechanged",{id:this.options.id,time:new Date(this.customTime.valueOf()),event:t}),t.stopPropagation())}},{key:"_onMarkerChange",value:function(t){this.body.emitter.emit("markerchange",{id:this.options.id,title:t.target.innerHTML,event:t}),t.stopPropagation()}},{key:"_onMarkerChanged",value:function(t){this.body.emitter.emit("markerchanged",{id:this.options.id,title:t.target.innerHTML,event:t}),t.stopPropagation()}}],[{key:"customTimeFromTarget",value:function(t){for(var e=t.target;e;){if(e.hasOwnProperty("custom-time"))return e["custom-time"];e=e.parentNode}return null}}]),i}(IE);pP("");pP('.vis-current-time{background-color:#ff7f6e;pointer-events:none;width:2px;z-index:1}.vis-rolling-mode-btn{background:#3876c2;border-radius:50%;color:#fff;cursor:pointer;font-size:28px;font-weight:700;height:40px;opacity:.8;position:absolute;right:20px;text-align:center;top:7px;width:40px}.vis-rolling-mode-btn:before{content:"\\26F6"}.vis-rolling-mode-btn:hover{opacity:1}');pP(".vis-panel{box-sizing:border-box;margin:0;padding:0;position:absolute}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right,.vis-panel.vis-top{border:1px #bfbfbf}.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right{border-bottom-style:solid;border-top-style:solid;overflow:hidden}.vis-left.vis-panel.vis-vertical-scroll,.vis-right.vis-panel.vis-vertical-scroll{height:100%;overflow-x:hidden;overflow-y:scroll}.vis-left.vis-panel.vis-vertical-scroll{direction:rtl}.vis-left.vis-panel.vis-vertical-scroll .vis-content,.vis-right.vis-panel.vis-vertical-scroll{direction:ltr}.vis-right.vis-panel.vis-vertical-scroll .vis-content{direction:rtl}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-top{border-left-style:solid;border-right-style:solid}.vis-background{overflow:hidden}.vis-panel>.vis-content{position:relative}.vis-panel .vis-shadow{box-shadow:0 0 10px rgba(0,0,0,.8);height:1px;position:absolute;width:100%}.vis-panel .vis-shadow.vis-top{left:0;top:-1px}.vis-panel .vis-shadow.vis-bottom{bottom:-1px;left:0}");pP(".vis-graph-group0{fill:#4f81bd;fill-opacity:0;stroke-width:2px;stroke:#4f81bd}.vis-graph-group1{fill:#f79646;fill-opacity:0;stroke-width:2px;stroke:#f79646}.vis-graph-group2{fill:#8c51cf;fill-opacity:0;stroke-width:2px;stroke:#8c51cf}.vis-graph-group3{fill:#75c841;fill-opacity:0;stroke-width:2px;stroke:#75c841}.vis-graph-group4{fill:#ff0100;fill-opacity:0;stroke-width:2px;stroke:#ff0100}.vis-graph-group5{fill:#37d8e6;fill-opacity:0;stroke-width:2px;stroke:#37d8e6}.vis-graph-group6{fill:#042662;fill-opacity:0;stroke-width:2px;stroke:#042662}.vis-graph-group7{fill:#00ff26;fill-opacity:0;stroke-width:2px;stroke:#00ff26}.vis-graph-group8{fill:#f0f;fill-opacity:0;stroke-width:2px;stroke:#f0f}.vis-graph-group9{fill:#8f3938;fill-opacity:0;stroke-width:2px;stroke:#8f3938}.vis-timeline .vis-fill{fill-opacity:.1;stroke:none}.vis-timeline .vis-bar{fill-opacity:.5;stroke-width:1px}.vis-timeline .vis-point{stroke-width:2px;fill-opacity:1}.vis-timeline .vis-legend-background{stroke-width:1px;fill-opacity:.9;fill:#fff;stroke:#c2c2c2}.vis-timeline .vis-outline{stroke-width:1px;fill-opacity:1;fill:#fff;stroke:#e5e5e5}.vis-timeline .vis-icon-fill{fill-opacity:.3;stroke:none}");pP(".vis-timeline{border:1px solid #bfbfbf;box-sizing:border-box;margin:0;overflow:hidden;padding:0;position:relative}.vis-loading-screen{height:100%;left:0;position:absolute;top:0;width:100%}");pP(".vis [class*=span]{min-height:0;width:auto}");var RP=function(){function t(){Ma(this,t)}return Yd(t,[{key:"_create",value:function(t){var e,i,n,r=this;this.dom={},this.dom.container=t,this.dom.container.style.position="relative",this.dom.root=document.createElement("div"),this.dom.background=document.createElement("div"),this.dom.backgroundVertical=document.createElement("div"),this.dom.backgroundHorizontal=document.createElement("div"),this.dom.centerContainer=document.createElement("div"),this.dom.leftContainer=document.createElement("div"),this.dom.rightContainer=document.createElement("div"),this.dom.center=document.createElement("div"),this.dom.left=document.createElement("div"),this.dom.right=document.createElement("div"),this.dom.top=document.createElement("div"),this.dom.bottom=document.createElement("div"),this.dom.shadowTop=document.createElement("div"),this.dom.shadowBottom=document.createElement("div"),this.dom.shadowTopLeft=document.createElement("div"),this.dom.shadowBottomLeft=document.createElement("div"),this.dom.shadowTopRight=document.createElement("div"),this.dom.shadowBottomRight=document.createElement("div"),this.dom.rollingModeBtn=document.createElement("div"),this.dom.loadingScreen=document.createElement("div"),this.dom.root.className="vis-timeline",this.dom.background.className="vis-panel vis-background",this.dom.backgroundVertical.className="vis-panel vis-background vis-vertical",this.dom.backgroundHorizontal.className="vis-panel vis-background vis-horizontal",this.dom.centerContainer.className="vis-panel vis-center",this.dom.leftContainer.className="vis-panel vis-left",this.dom.rightContainer.className="vis-panel vis-right",this.dom.top.className="vis-panel vis-top",this.dom.bottom.className="vis-panel vis-bottom",this.dom.left.className="vis-content",this.dom.center.className="vis-content",this.dom.right.className="vis-content",this.dom.shadowTop.className="vis-shadow vis-top",this.dom.shadowBottom.className="vis-shadow vis-bottom",this.dom.shadowTopLeft.className="vis-shadow vis-top",this.dom.shadowBottomLeft.className="vis-shadow vis-bottom",this.dom.shadowTopRight.className="vis-shadow vis-top",this.dom.shadowBottomRight.className="vis-shadow vis-bottom",this.dom.rollingModeBtn.className="vis-rolling-mode-btn",this.dom.loadingScreen.className="vis-loading-screen",this.dom.root.appendChild(this.dom.background),this.dom.root.appendChild(this.dom.backgroundVertical),this.dom.root.appendChild(this.dom.backgroundHorizontal),this.dom.root.appendChild(this.dom.centerContainer),this.dom.root.appendChild(this.dom.leftContainer),this.dom.root.appendChild(this.dom.rightContainer),this.dom.root.appendChild(this.dom.top),this.dom.root.appendChild(this.dom.bottom),this.dom.root.appendChild(this.dom.rollingModeBtn),this.dom.centerContainer.appendChild(this.dom.center),this.dom.leftContainer.appendChild(this.dom.left),this.dom.rightContainer.appendChild(this.dom.right),this.dom.centerContainer.appendChild(this.dom.shadowTop),this.dom.centerContainer.appendChild(this.dom.shadowBottom),this.dom.leftContainer.appendChild(this.dom.shadowTopLeft),this.dom.leftContainer.appendChild(this.dom.shadowBottomLeft),this.dom.rightContainer.appendChild(this.dom.shadowTopRight),this.dom.rightContainer.appendChild(this.dom.shadowBottomRight),this.props={root:{},background:{},centerContainer:{},leftContainer:{},rightContainer:{},center:{},left:{},right:{},top:{},bottom:{},border:{},scrollTop:0,scrollTopMin:0},this.on("rangechange",(function(){!0===r.initialDrawDone&&r._redraw()})),this.on("rangechanged",(function(){r.initialRangeChangeDone||(r.initialRangeChangeDone=!0)})),this.on("touch",Tp(e=this._onTouch).call(e,this)),this.on("panmove",Tp(i=this._onDrag).call(i,this));var o=this;this._origRedraw=Tp(n=this._redraw).call(n,this),this._redraw=wE.throttle(this._origRedraw),this.on("_change",(function(t){o.itemSet&&o.itemSet.initialItemSetDrawn&&t&&1==t.queue?o._redraw():o._origRedraw()})),this.hammer=new uP(this.dom.root);var s=this.hammer.get("pinch").set({enable:!0});s&&function(t){t.getTouchAction=function(){return["pan-y"]}}(s),this.hammer.get("pan").set({threshold:5,direction:uP.DIRECTION_ALL}),this.timelineListeners={};var a,l,h=["tap","doubletap","press","pinch","pan","panstart","panmove","panend"];function u(t){this.isActive()&&this.emit("mousewheel",t);var e=0,i=0;if("detail"in t&&(i=-1*t.detail),"wheelDelta"in t&&(i=t.wheelDelta),"wheelDeltaY"in t&&(i=t.wheelDeltaY),"wheelDeltaX"in t&&(e=-1*t.wheelDeltaX),"axis"in t&&t.axis===t.HORIZONTAL_AXIS&&(e=-1*i,i=0),"deltaY"in t&&(i=-1*t.deltaY),"deltaX"in t&&(e=t.deltaX),t.deltaMode&&(1===t.deltaMode?(e*=40,i*=40):(e*=40,i*=800)),this.options.preferZoom){if(!this.options.zoomKey||t[this.options.zoomKey])return}else if(this.options.zoomKey&&t[this.options.zoomKey])return;if(this.options.verticalScroll||this.options.horizontalScroll)if(this.options.verticalScroll&&Math.abs(i)>=Math.abs(e)){var n=this.props.scrollTop,r=n+i;if(this.isActive())this._setScrollTop(r)!==n&&(this._redraw(),this.emit("scroll",t),t.preventDefault())}else if(this.options.horizontalScroll){var o=(Math.abs(e)>=Math.abs(i)?e:i)/120*(this.range.end-this.range.start)/20,s=this.range.start+o,a=this.range.end+o,l={animation:!1,byUser:!0,event:t};this.range.setRange(s,a,l),t.preventDefault()}}Hp(h).call(h,(function(t){var e=function(e){o.isActive()&&o.emit(t,e)};o.hammer.on(t,e),o.timelineListeners[t]=e})),dP(this.hammer,(function(t){o.emit("touch",t)})),a=this.hammer,(l=function(t){o.emit("release",t)}).inputHandler=function(t){t.isFinal&&l(t)},a.on("hammer.input",l.inputHandler);var d="onwheel"in document.createElement("div")?"wheel":void 0!==document.onmousewheel?"mousewheel":this.dom.centerContainer.addEventListener?"DOMMouseScroll":"onmousewheel";function c(t){if(o.options.verticalScroll&&(t.preventDefault(),o.isActive())){var e=-t.target.scrollTop;o._setScrollTop(e),o._redraw(),o.emit("scrollSide",t)}}this.dom.top.addEventListener,this.dom.bottom.addEventListener,this.dom.centerContainer.addEventListener(d,Tp(u).call(u,this),!1),this.dom.top.addEventListener(d,Tp(u).call(u,this),!1),this.dom.bottom.addEventListener(d,Tp(u).call(u,this),!1),this.dom.left.parentNode.addEventListener("scroll",Tp(c).call(c,this)),this.dom.right.parentNode.addEventListener("scroll",Tp(c).call(c,this));var p=!1;function f(t){var e;if(t.preventDefault&&(o.emit("dragover",o.getEventProperties(t)),t.preventDefault()),av(e=t.target.className).call(e,"timeline")>-1&&!p)return t.dataTransfer.dropEffect="move",p=!0,!1}function m(t){t.preventDefault&&t.preventDefault(),t.stopPropagation&&t.stopPropagation();try{var e=JSON.parse(t.dataTransfer.getData("text"));if(!e||!e.content)return}catch(t){return!1}return p=!1,t.center={x:t.clientX,y:t.clientY},"item"!==e.target?o.itemSet._onAddItem(t):o.itemSet._onDropObjectOnItem(t),o.emit("drop",o.getEventProperties(t)),!1}if(this.dom.center.addEventListener("dragover",Tp(f).call(f,this),!1),this.dom.center.addEventListener("drop",Tp(m).call(m,this),!1),this.customTimes=[],this.touch={},this.redrawCount=0,this.initialDrawDone=!1,this.initialRangeChangeDone=!1,!t)throw new Error("No container provided");t.appendChild(this.dom.root),t.appendChild(this.dom.loadingScreen)}},{key:"setOptions",value:function(t){var e;if(t){if(wE.selectiveExtend(["width","height","minHeight","maxHeight","autoResize","start","end","clickToUse","dataAttributes","hiddenDates","locale","locales","moment","preferZoom","rtl","zoomKey","horizontalScroll","verticalScroll","longSelectPressTime","snap"],this.options,t),this.dom.rollingModeBtn.style.visibility="hidden",this.options.rtl&&(this.dom.container.style.direction="rtl",this.dom.backgroundVertical.className="vis-panel vis-background vis-vertical-rtl"),this.options.verticalScroll&&(this.options.rtl?this.dom.rightContainer.className="vis-panel vis-right vis-vertical-scroll":this.dom.leftContainer.className="vis-panel vis-left vis-vertical-scroll"),"object"!==Nd(this.options.orientation)&&(this.options.orientation={item:void 0,axis:void 0}),"orientation"in t&&("string"==typeof t.orientation?this.options.orientation={item:t.orientation,axis:t.orientation}:"object"===Nd(t.orientation)&&("item"in t.orientation&&(this.options.orientation.item=t.orientation.item),"axis"in t.orientation&&(this.options.orientation.axis=t.orientation.axis))),"both"===this.options.orientation.axis){if(!this.timeAxis2){var i=this.timeAxis2=new mP(this.body,this.options);i.setOptions=function(t){var e=t?wE.extend({},t):{};e.orientation="top",mP.prototype.setOptions.call(i,e)},this.components.push(i)}}else if(this.timeAxis2){var n,r,o=av(n=this.components).call(n,this.timeAxis2);if(-1!==o)_f(r=this.components).call(r,o,1);this.timeAxis2.destroy(),this.timeAxis2=null}"function"==typeof t.drawPoints&&(t.drawPoints={onRender:t.drawPoints}),"hiddenDates"in this.options&&WE(this.options.moment,this.body,this.options.hiddenDates),"clickToUse"in t&&(t.clickToUse?this.activator||(this.activator=new yP(this.dom.root)):this.activator&&(this.activator.destroy(),delete this.activator)),this._initAutoResize()}if(Hp(e=this.components).call(e,(function(e){return e.setOptions(t)})),"configure"in t){var s;this.configurator||(this.configurator=this._createConfigurator()),this.configurator.setOptions(t.configure);var a=wE.deepExtend({},this.options);Hp(s=this.components).call(s,(function(t){wE.deepExtend(a,t.options)})),this.configurator.setModuleOptions({global:a})}this._redraw()}},{key:"isActive",value:function(){return!this.activator||this.activator.active}},{key:"destroy",value:function(){var t;for(var e in this.setItems(null),this.setGroups(null),this.off(),this._stopAutoResize(),this.dom.root.parentNode&&this.dom.root.parentNode.removeChild(this.dom.root),this.dom=null,this.activator&&(this.activator.destroy(),delete this.activator),this.timelineListeners)this.timelineListeners.hasOwnProperty(e)&&delete this.timelineListeners[e];this.timelineListeners=null,this.hammer&&this.hammer.destroy(),this.hammer=null,Hp(t=this.components).call(t,(function(t){return t.destroy()})),this.body=null}},{key:"setCustomTime",value:function(t,e){var i,n=mm(i=this.customTimes).call(i,(function(t){return e===t.options.id}));if(0===n.length)throw new Error("No custom time bar found with id ".concat(vv(e)));n.length>0&&n[0].setCustomTime(t)}},{key:"getCustomTime",value:function(t){var e,i=mm(e=this.customTimes).call(e,(function(e){return e.options.id===t}));if(0===i.length)throw new Error("No custom time bar found with id ".concat(vv(t)));return i[0].getCustomTime()}},{key:"setCustomTimeMarker",value:function(t,e,i){var n,r=mm(n=this.customTimes).call(n,(function(t){return t.options.id===e}));if(0===r.length)throw new Error("No custom time bar found with id ".concat(vv(e)));r.length>0&&r[0].setCustomMarker(t,i)}},{key:"setCustomTimeTitle",value:function(t,e){var i,n=mm(i=this.customTimes).call(i,(function(t){return t.options.id===e}));if(0===n.length)throw new Error("No custom time bar found with id ".concat(vv(e)));if(n.length>0)return n[0].setCustomTitle(t)}},{key:"getEventProperties",value:function(t){return{event:t}}},{key:"addCustomTime",value:function(t,e){var i,n=void 0!==t?wE.convert(t,"Date"):new Date,r=TT(i=this.customTimes).call(i,(function(t){return t.options.id===e}));if(r)throw new Error("A custom time with id ".concat(vv(e)," already exists"));var o=new NP(this.body,wE.extend({},this.options,{time:n,id:e,snap:this.itemSet?this.itemSet.options.snap:this.options.snap}));return this.customTimes.push(o),this.components.push(o),this._redraw(),e}},{key:"removeCustomTime",value:function(t){var e,i=this,n=mm(e=this.customTimes).call(e,(function(e){return e.options.id===t}));if(0===n.length)throw new Error("No custom time bar found with id ".concat(vv(t)));Hp(n).call(n,(function(t){var e,n,r,o;_f(e=i.customTimes).call(e,av(n=i.customTimes).call(n,t),1),_f(r=i.components).call(r,av(o=i.components).call(o,t),1),t.destroy()}))}},{key:"getVisibleItems",value:function(){return this.itemSet&&this.itemSet.getVisibleItems()||[]}},{key:"getItemsAtCurrentTime",value:function(t){return this.time=t,this.itemSet&&this.itemSet.getItemsAtCurrentTime(this.time)||[]}},{key:"getVisibleGroups",value:function(){return this.itemSet&&this.itemSet.getVisibleGroups()||[]}},{key:"fit",value:function(t,e){var i=this.getDataRange();if(null!==i.min||null!==i.max){var n=i.max-i.min,r=new Date(i.min.valueOf()-.01*n),o=new Date(i.max.valueOf()+.01*n),s=!t||void 0===t.animation||t.animation;this.range.setRange(r,o,{animation:s},e)}}},{key:"getDataRange",value:function(){throw new Error("Cannot invoke abstract method getDataRange")}},{key:"setWindow",value:function(t,e,i,n){var r,o;"function"==typeof arguments[2]&&(n=arguments[2],i={}),1==arguments.length?(r=void 0===(o=arguments[0]).animation||o.animation,this.range.setRange(o.start,o.end,{animation:r})):2==arguments.length&&"function"==typeof arguments[1]?(n=arguments[1],r=void 0===(o=arguments[0]).animation||o.animation,this.range.setRange(o.start,o.end,{animation:r},n)):(r=!i||void 0===i.animation||i.animation,this.range.setRange(t,e,{animation:r},n))}},{key:"moveTo",value:function(t,e,i){"function"==typeof arguments[1]&&(i=arguments[1],e={});var n=this.range.end-this.range.start,r=wE.convert(t,"Date").valueOf(),o=r-n/2,s=r+n/2,a=!e||void 0===e.animation||e.animation;this.range.setRange(o,s,{animation:a},i)}},{key:"getWindow",value:function(){var t=this.range.getRange();return{start:new Date(t.start),end:new Date(t.end)}}},{key:"zoomIn",value:function(t,e,i){if(!(!t||t<0||t>1)){"function"==typeof arguments[1]&&(i=arguments[1],e={});var n=this.getWindow(),r=n.start.valueOf(),o=n.end.valueOf(),s=o-r,a=(s-s/(1+t))/2,l=r+a,h=o-a;this.setWindow(l,h,e,i)}}},{key:"zoomOut",value:function(t,e,i){if(!(!t||t<0||t>1)){"function"==typeof arguments[1]&&(i=arguments[1],e={});var n=this.getWindow(),r=n.start.valueOf(),o=n.end.valueOf(),s=o-r,a=r-s*t/2,l=o+s*t/2;this.setWindow(a,l,e,i)}}},{key:"redraw",value:function(){this._redraw()}},{key:"_redraw",value:function(){var t;this.redrawCount++;var e=this.dom;if(e&&e.container&&0!=e.root.offsetWidth){var i=!1,n=this.options,r=this.props;VE(this.options.moment,this.body,this.options.hiddenDates),"top"==n.orientation?(wE.addClassName(e.root,"vis-top"),wE.removeClassName(e.root,"vis-bottom")):(wE.removeClassName(e.root,"vis-top"),wE.addClassName(e.root,"vis-bottom")),n.rtl?(wE.addClassName(e.root,"vis-rtl"),wE.removeClassName(e.root,"vis-ltr")):(wE.addClassName(e.root,"vis-ltr"),wE.removeClassName(e.root,"vis-rtl")),e.root.style.maxHeight=wE.option.asSize(n.maxHeight,""),e.root.style.minHeight=wE.option.asSize(n.minHeight,""),e.root.style.width=wE.option.asSize(n.width,"");var o=e.root.offsetWidth;r.border.left=1,r.border.right=1,r.border.top=1,r.border.bottom=1,r.center.height=e.center.offsetHeight,r.left.height=e.left.offsetHeight,r.right.height=e.right.offsetHeight,r.top.height=e.top.clientHeight||-r.border.top,r.bottom.height=Math.round(e.bottom.getBoundingClientRect().height)||e.bottom.clientHeight||-r.border.bottom;var s=Math.max(r.left.height,r.center.height,r.right.height),a=r.top.height+s+r.bottom.height+r.border.top+r.border.bottom;e.root.style.height=wE.option.asSize(n.height,"".concat(a,"px")),r.root.height=e.root.offsetHeight,r.background.height=r.root.height;var l=r.root.height-r.top.height-r.bottom.height;r.centerContainer.height=l,r.leftContainer.height=l,r.rightContainer.height=r.leftContainer.height,r.root.width=o,r.background.width=r.root.width,this.initialDrawDone||(r.scrollbarWidth=wE.getScrollBarWidth());var h=e.leftContainer.clientWidth,u=e.rightContainer.clientWidth;n.verticalScroll?n.rtl?(r.left.width=h||-r.border.left,r.right.width=u+r.scrollbarWidth||-r.border.right):(r.left.width=h+r.scrollbarWidth||-r.border.left,r.right.width=u||-r.border.right):(r.left.width=h||-r.border.left,r.right.width=u||-r.border.right),this._setDOM();var d=this._updateScrollTop();"top"!=n.orientation.item&&(d+=Math.max(r.centerContainer.height-r.center.height-r.border.top-r.border.bottom,0)),e.center.style.transform="translateY(".concat(d,"px)");var c=0==r.scrollTop?"hidden":"",p=r.scrollTop==r.scrollTopMin?"hidden":"";e.shadowTop.style.visibility=c,e.shadowBottom.style.visibility=p,e.shadowTopLeft.style.visibility=c,e.shadowBottomLeft.style.visibility=p,e.shadowTopRight.style.visibility=c,e.shadowBottomRight.style.visibility=p,n.verticalScroll&&(e.rightContainer.className="vis-panel vis-right vis-vertical-scroll",e.leftContainer.className="vis-panel vis-left vis-vertical-scroll",e.shadowTopRight.style.visibility="hidden",e.shadowBottomRight.style.visibility="hidden",e.shadowTopLeft.style.visibility="hidden",e.shadowBottomLeft.style.visibility="hidden",e.left.style.top="0px",e.right.style.top="0px"),(!n.verticalScroll||r.center.heightr.centerContainer.height;this.hammer.get("pan").set({direction:f?uP.DIRECTION_ALL:uP.DIRECTION_HORIZONTAL}),this.hammer.get("press").set({time:this.options.longSelectPressTime}),Hp(t=this.components).call(t,(function(t){i=t.redraw()||i}));if(i){if(this.redrawCount<5)return void this.body.emitter.emit("_change");console.log("WARNING: infinite loop in redraw?")}else this.redrawCount=0;this.body.emitter.emit("changed")}}},{key:"_setDOM",value:function(){var t=this.props,e=this.dom;t.leftContainer.width=t.left.width,t.rightContainer.width=t.right.width;var i=t.root.width-t.left.width-t.right.width;t.center.width=i,t.centerContainer.width=i,t.top.width=i,t.bottom.width=i,e.background.style.height="".concat(t.background.height,"px"),e.backgroundVertical.style.height="".concat(t.background.height,"px"),e.backgroundHorizontal.style.height="".concat(t.centerContainer.height,"px"),e.centerContainer.style.height="".concat(t.centerContainer.height,"px"),e.leftContainer.style.height="".concat(t.leftContainer.height,"px"),e.rightContainer.style.height="".concat(t.rightContainer.height,"px"),e.background.style.width="".concat(t.background.width,"px"),e.backgroundVertical.style.width="".concat(t.centerContainer.width,"px"),e.backgroundHorizontal.style.width="".concat(t.background.width,"px"),e.centerContainer.style.width="".concat(t.center.width,"px"),e.top.style.width="".concat(t.top.width,"px"),e.bottom.style.width="".concat(t.bottom.width,"px"),e.background.style.left="0",e.background.style.top="0",e.backgroundVertical.style.left="".concat(t.left.width+t.border.left,"px"),e.backgroundVertical.style.top="0",e.backgroundHorizontal.style.left="0",e.backgroundHorizontal.style.top="".concat(t.top.height,"px"),e.centerContainer.style.left="".concat(t.left.width,"px"),e.centerContainer.style.top="".concat(t.top.height,"px"),e.leftContainer.style.left="0",e.leftContainer.style.top="".concat(t.top.height,"px"),e.rightContainer.style.left="".concat(t.left.width+t.center.width,"px"),e.rightContainer.style.top="".concat(t.top.height,"px"),e.top.style.left="".concat(t.left.width,"px"),e.top.style.top="0",e.bottom.style.left="".concat(t.left.width,"px"),e.bottom.style.top="".concat(t.top.height+t.centerContainer.height,"px"),e.center.style.left="0",e.left.style.left="0",e.right.style.left="0"}},{key:"setCurrentTime",value:function(t){if(!this.currentTime)throw new Error("Option showCurrentTime must be true");this.currentTime.setCurrentTime(t)}},{key:"getCurrentTime",value:function(){if(!this.currentTime)throw new Error("Option showCurrentTime must be true");return this.currentTime.getCurrentTime()}},{key:"_toTime",value:function(t){return $E(this,t,this.props.center.width)}},{key:"_toGlobalTime",value:function(t){return $E(this,t,this.props.root.width)}},{key:"_toScreen",value:function(t){return qE(this,t,this.props.center.width)}},{key:"_toGlobalScreen",value:function(t){return qE(this,t,this.props.root.width)}},{key:"_initAutoResize",value:function(){1==this.options.autoResize?this._startAutoResize():this._stopAutoResize()}},{key:"_startAutoResize",value:function(){var t=this;this._stopAutoResize(),this._onResize=function(){if(1==t.options.autoResize){if(t.dom.root){var e=t.dom.root.offsetHeight,i=t.dom.root.offsetWidth;i==t.props.lastWidth&&e==t.props.lastHeight||(t.props.lastWidth=i,t.props.lastHeight=e,t.props.scrollbarWidth=wE.getScrollBarWidth(),t.body.emitter.emit("_change"))}}else t._stopAutoResize()},window.addEventListener("resize",this._onResize),t.dom.root&&(t.props.lastWidth=t.dom.root.offsetWidth,t.props.lastHeight=t.dom.root.offsetHeight),this.watchTimer=lP(this._onResize,1e3)}},{key:"_stopAutoResize",value:function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0),this._onResize&&(window.removeEventListener("resize",this._onResize),this._onResize=null)}},{key:"_onTouch",value:function(t){this.touch.allowDragging=!0,this.touch.initialScrollTop=this.props.scrollTop}},{key:"_onPinch",value:function(t){this.touch.allowDragging=!1}},{key:"_onDrag",value:function(t){if(t&&this.touch.allowDragging){var e=t.deltaY,i=this._getScrollTop(),n=this._setScrollTop(this.touch.initialScrollTop+e);this.options.verticalScroll&&(this.dom.left.parentNode.scrollTop=-this.props.scrollTop,this.dom.right.parentNode.scrollTop=-this.props.scrollTop),n!=i&&this.emit("verticalDrag")}}},{key:"_setScrollTop",value:function(t){return this.props.scrollTop=t,this._updateScrollTop(),this.props.scrollTop}},{key:"_updateScrollTop",value:function(){var t=Math.min(this.props.centerContainer.height-this.props.border.top-this.props.border.bottom-this.props.center.height,0);return t!=this.props.scrollTopMin&&("top"!=this.options.orientation.item&&(this.props.scrollTop+=t-this.props.scrollTopMin),this.props.scrollTopMin=t),this.props.scrollTop>0&&(this.props.scrollTop=0),this.props.scrollTop1e3&&(i=1e3),t.redraw(),t.body.emitter.emit("currentTimeTick"),t.currentTimeTimer=Rv(e,i)}()}},{key:"stop",value:function(){void 0!==this.currentTimeTimer&&(clearTimeout(this.currentTimeTimer),delete this.currentTimeTimer)}},{key:"setCurrentTime",value:function(t){var e=wE.convert(t,"Date").valueOf(),i=lp();this.offset=e-i,this.redraw()}},{key:"getCurrentTime",value:function(){return new Date(lp()+this.offset)}}]),i}(IE),YP=En,HP=Zl.find,zP="find",BP=!0;zP in[]&&Array(1)[zP]((function(){BP=!1})),YP({target:"Array",proto:!0,forced:BP},{find:function(t){return HP(this,t,arguments.length>1?arguments[1]:void 0)}});var GP=Jd("Array").find,WP=ye,VP=GP,UP=Array.prototype,XP=function(t){var e=t.find;return t===UP||WP(UP,t)&&e===UP.find?VP:e},qP=n(XP),$P=En,ZP=Zl.findIndex,KP="findIndex",JP=!0;KP in[]&&Array(1)[KP]((function(){JP=!1})),$P({target:"Array",proto:!0,forced:JP},{findIndex:function(t){return ZP(this,t,arguments.length>1?arguments[1]:void 0)}});var QP=Jd("Array").findIndex,tA=ye,eA=QP,iA=Array.prototype,nA=function(t){var e=t.findIndex;return t===iA||tA(iA,t)&&e===iA.findIndex?eA:e},rA=n(nA);function oA(t,e){var i=void 0!==Ic&&Ta(t)||t["@@iterator"];if(!i){if(qc(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return sA(t,e);var n=Hc(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return sa(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return sA(t,e)}(t))||e&&t&&"number"==typeof t.length){i&&(t=i);var n=0,r=function(){};return{s:r,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function sA(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);ie.index?1:t.indexi[a].index&&(i[o].top+=i[a].height);for(var l=t[o],h=0;he}),m),_f(p).call(p,m,0,t),m++}};for(v.s();!(d=v.n()).done;)g()}catch(t){v.e(t)}finally{v.f()}f=null;var y=null;m=0;for(var b,_=0,w=0,k=0,x=function(){var t,n,r=c.shift();r.top=s(r);var u=l(r),d=h(r);null!==f&&ud&&(w=function(t,e,n,r){n||(n=0);r||(r=t.length);for(i=r-1;i>=n;i--)if(e(t[i]))return i;return n-1}(p,(function(t){return d+aA>=l(t)}),_,w)+1);for(var v,g,b,x=_T(t=mm(n=Hc(p).call(p,_,w)).call(n,(function(t){return ul(t)}))).call(t,(function(t,e){return t.top-e.top})),D=0;Dg.top&&(r.top=S.top+S.height+e.vertical)}o(r)&&(m=vA(p,(function(t){return l(t)-aA>u}),m),_f(p).call(p,m,0,r),m++);var C=r.top+r.height;if(C>k&&(k=C),a&&a())return{v:null}};c.length>0;)if(b=x())return b.v;return k}function vA(t,e,i){var n;i||(i=0);var r=rA(n=Hc(t).call(t,i)).call(n,e);return-1===r?t.length:r+i}var gA=Object.freeze({__proto__:null,nostack:cA,orderByEnd:hA,orderByStart:lA,stack:uA,stackSubgroups:pA,stackSubgroupsWithInnerStack:fA,substack:dA}),yA="__background__",bA=function(){function t(e,i,n){var r=this;if(Ma(this,t),this.groupId=e,this.subgroups={},this.subgroupStack={},this.subgroupStackAll=!1,this.subgroupVisibility={},this.doInnerStack=!1,this.shouldBailStackItems=!1,this.subgroupIndex=0,this.subgroupOrderer=i&&i.subgroupOrder,this.itemSet=n,this.isVisible=null,this.stackDirty=!0,this._disposeCallbacks=[],i&&i.nestedGroups&&(this.nestedGroups=i.nestedGroups,0==i.showNested?this.showNested=!1:this.showNested=!0),i&&i.subgroupStack)if("boolean"==typeof i.subgroupStack)this.doInnerStack=i.subgroupStack,this.subgroupStackAll=i.subgroupStack;else for(var o in i.subgroupStack)this.subgroupStack[o]=i.subgroupStack[o],this.doInnerStack=this.doInnerStack||i.subgroupStack[o];i&&i.heightMode?this.heightMode=i.heightMode:this.heightMode=n.options.groupHeightMode,this.nestedInGroup=null,this.dom={},this.props={label:{width:0,height:0}},this.className=null,this.items={},this.visibleItems=[],this.itemsInRange=[],this.orderedItems={byStart:[],byEnd:[]},this.checkRangedItems=!1;var s=function(){r.checkRangedItems=!0};this.itemSet.body.emitter.on("checkRangedItems",s),this._disposeCallbacks.push((function(){r.itemSet.body.emitter.off("checkRangedItems",s)})),this._create(),this.setData(i)}return Yd(t,[{key:"_create",value:function(){var t=document.createElement("div");this.itemSet.options.groupEditable.order?t.className="vis-label draggable":t.className="vis-label",this.dom.label=t;var e=document.createElement("div");e.className="vis-inner",t.appendChild(e),this.dom.inner=e;var i=document.createElement("div");i.className="vis-group",i["vis-group"]=this,this.dom.foreground=i,this.dom.background=document.createElement("div"),this.dom.background.className="vis-group",this.dom.axis=document.createElement("div"),this.dom.axis.className="vis-group",this.dom.marker=document.createElement("div"),this.dom.marker.style.visibility="hidden",this.dom.marker.style.position="absolute",this.dom.marker.innerHTML="",this.dom.background.appendChild(this.dom.marker)}},{key:"setData",value:function(t){if(!this.itemSet.groupTouchParams.isDragging){var e,i,n;if(t&&t.subgroupVisibility)for(var r in t.subgroupVisibility)this.subgroupVisibility[r]=t.subgroupVisibility[r];if(this.itemSet.options&&this.itemSet.options.groupTemplate)e=(i=Tp(n=this.itemSet.options.groupTemplate).call(n,this))(t,this.dom.inner);else e=t&&t.content;if(e instanceof Element){for(;this.dom.inner.firstChild;)this.dom.inner.removeChild(this.dom.inner.firstChild);this.dom.inner.appendChild(e)}else e instanceof Object&&e.isReactComponent||(e instanceof Object?i(t,this.dom.inner):this.dom.inner.innerHTML=null!=e?wE.xss(e):wE.xss(this.groupId||""));this.dom.label.title=t&&t.title||"",this.dom.inner.firstChild?wE.removeClassName(this.dom.inner,"vis-hidden"):wE.addClassName(this.dom.inner,"vis-hidden"),t&&t.nestedGroups?(this.nestedGroups&&this.nestedGroups==t.nestedGroups||(this.nestedGroups=t.nestedGroups),void 0===t.showNested&&void 0!==this.showNested||(0==t.showNested?this.showNested=!1:this.showNested=!0),wE.addClassName(this.dom.label,"vis-nesting-group"),this.showNested?(wE.removeClassName(this.dom.label,"collapsed"),wE.addClassName(this.dom.label,"expanded")):(wE.removeClassName(this.dom.label,"expanded"),wE.addClassName(this.dom.label,"collapsed"))):this.nestedGroups&&(this.nestedGroups=null,wE.removeClassName(this.dom.label,"collapsed"),wE.removeClassName(this.dom.label,"expanded"),wE.removeClassName(this.dom.label,"vis-nesting-group")),t&&(t.treeLevel||t.nestedInGroup)?(wE.addClassName(this.dom.label,"vis-nested-group"),t.treeLevel?wE.addClassName(this.dom.label,"vis-group-level-"+t.treeLevel):wE.addClassName(this.dom.label,"vis-group-level-unknown-but-gte1")):wE.addClassName(this.dom.label,"vis-group-level-0");var o=t&&t.className||null;o!=this.className&&(this.className&&(wE.removeClassName(this.dom.label,this.className),wE.removeClassName(this.dom.foreground,this.className),wE.removeClassName(this.dom.background,this.className),wE.removeClassName(this.dom.axis,this.className)),wE.addClassName(this.dom.label,o),wE.addClassName(this.dom.foreground,o),wE.addClassName(this.dom.background,o),wE.addClassName(this.dom.axis,o),this.className=o),this.style&&(wE.removeCssText(this.dom.label,this.style),this.style=null),t&&t.style&&(wE.addCssText(this.dom.label,t.style),this.style=t.style)}}},{key:"getLabelWidth",value:function(){return this.props.label.width}},{key:"_didMarkerHeightChange",value:function(){var t=this.dom.marker.clientHeight;if(t!=this.lastMarkerHeight){this.lastMarkerHeight=t;var e={},i=0;if(Hp(wE).call(wE,this.items,(function(t,n){if(t.dirty=!0,t.displayed){e[n]=t.redraw(!0),i=e[n].length}})),i>0)for(var n=function(t){Hp(wE).call(wE,e,(function(e){e[t]()}))},r=0;ri.bailTimeMs&&(i.userBailFunction&&null==this.itemSet.userContinueNotBail?i.userBailFunction((function(e){t.itemSet.userContinueNotBail=e,n=!e})):n=0==t.itemSet.userContinueNotBail)}return n}},{key:"_redrawItems",value:function(t,e,i,n){var r=this;if(t||this.stackDirty||this.isVisible&&!e){var o,s,a,l,h,u,d={byEnd:mm(o=this.orderedItems.byEnd).call(o,(function(t){return!t.isCluster})),byStart:mm(s=this.orderedItems.byStart).call(s,(function(t){return!t.isCluster}))},c={byEnd:Ac(new LC(mm(a=ep(l=this.orderedItems.byEnd).call(l,(function(t){return t.cluster}))).call(a,(function(t){return!!t})))),byStart:Ac(new LC(mm(h=ep(u=this.orderedItems.byStart).call(u,(function(t){return t.cluster}))).call(h,(function(t){return!!t}))))},p=function(){var t,e,i,o=r._updateItemsInRange(d,mm(t=r.visibleItems).call(t,(function(t){return!t.isCluster})),n),s=r._updateClustersInRange(c,mm(e=r.visibleItems).call(e,(function(t){return t.isCluster})),n);return Yc(i=[]).call(i,Ac(o),Ac(s))},f=function(t){var e={},i=function(i){var n,o=mm(n=r.visibleItems).call(n,(function(t){return t.data.subgroup===i}));e[i]=t?_T(o).call(o,(function(e,i){return t(e.data,i.data)})):o};for(var n in r.subgroups)i(n);return e};if("function"==typeof this.itemSet.options.order){var m=this;if(this.doInnerStack&&this.itemSet.options.stackSubgroups){fA(f(this.itemSet.options.order),i,this.subgroups),this.visibleItems=p(),this._updateSubGroupHeights(i)}else{var v,g,y,b;this.visibleItems=p(),this._updateSubGroupHeights(i);var _=_T(v=mm(g=Hc(y=this.visibleItems).call(y)).call(g,(function(t){return t.isCluster||!t.isCluster&&!t.cluster}))).call(v,(function(t,e){return m.itemSet.options.order(t.data,e.data)}));this.shouldBailStackItems=uA(_,i,!0,Tp(b=this._shouldBailItemsRedraw).call(b,this))}}else{var w;if(this.visibleItems=p(),this._updateSubGroupHeights(i),this.itemSet.options.stack)if(this.doInnerStack&&this.itemSet.options.stackSubgroups)fA(f(),i,this.subgroups);else this.shouldBailStackItems=uA(this.visibleItems,i,!0,Tp(w=this._shouldBailItemsRedraw).call(w,this));else cA(this.visibleItems,i,this.subgroups,this.itemSet.options.stackSubgroups)}for(var k=0;k0){var i=this;this._resetSubgroups(),Hp(wE).call(wE,this.visibleItems,(function(n){void 0!==n.data.subgroup&&(i.subgroups[n.data.subgroup].height=Math.max(i.subgroups[n.data.subgroup].height,n.height+t.item.vertical),i.subgroups[n.data.subgroup].visible=void 0===e.subgroupVisibility[n.data.subgroup]||Boolean(e.subgroupVisibility[n.data.subgroup]))}))}}},{key:"_isGroupVisible",value:function(t,e){return this.top<=t.body.domProps.centerContainer.height-t.body.domProps.scrollTop+e.axis&&this.top+this.height+e.axis>=-t.body.domProps.scrollTop}},{key:"_calculateHeight",value:function(t){var e,i;if((i="fixed"===this.heightMode?wE.toArray(this.items):this.visibleItems).length>0){var n=i[0].top,r=i[0].top+i[0].height;if(Hp(wE).call(wE,i,(function(t){n=Math.min(n,t.top),r=Math.max(r,t.top+t.height)})),n>t.axis){var o=n-t.axis;r-=o,Hp(wE).call(wE,i,(function(t){t.top-=o}))}e=Math.ceil(r+t.item.vertical/2),"fitItems"!==this.heightMode&&(e=Math.max(e,this.props.label.height))}else e=this.props.label.height;return e}},{key:"show",value:function(){this.dom.label.parentNode||this.itemSet.dom.labelSet.appendChild(this.dom.label),this.dom.foreground.parentNode||this.itemSet.dom.foreground.appendChild(this.dom.foreground),this.dom.background.parentNode||this.itemSet.dom.background.appendChild(this.dom.background),this.dom.axis.parentNode||this.itemSet.dom.axis.appendChild(this.dom.axis)}},{key:"hide",value:function(){var t=this.dom.label;t.parentNode&&t.parentNode.removeChild(t);var e=this.dom.foreground;e.parentNode&&e.parentNode.removeChild(e);var i=this.dom.background;i.parentNode&&i.parentNode.removeChild(i);var n=this.dom.axis;n.parentNode&&n.parentNode.removeChild(n)}},{key:"add",value:function(t){var e;if(this.items[t.id]=t,t.setParent(this),this.stackDirty=!0,void 0!==t.data.subgroup&&(this._addToSubgroup(t),this.orderSubgroups()),!nm(e=this.visibleItems).call(e,t)){var i=this.itemSet.body.range;this._checkIfVisible(t,this.visibleItems,i)}}},{key:"_addToSubgroup",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t.data.subgroup;null!=e&&void 0===this.subgroups[e]&&(this.subgroups[e]={height:0,top:0,start:t.data.start,end:t.data.end||t.data.start,visible:!1,index:this.subgroupIndex,items:[],stack:this.subgroupStackAll||this.subgroupStack[e]||!1},this.subgroupIndex++),new Date(t.data.start)new Date(this.subgroups[e].end)&&(this.subgroups[e].end=i),this.subgroups[e].items.push(t)}},{key:"_updateSubgroupsSizes",value:function(){var t=this;if(t.subgroups){var e=function(){var e,n=t.subgroups[i].items[0].data.end||t.subgroups[i].items[0].data.start,r=t.subgroups[i].items[0].data.start,o=n-1;Hp(e=t.subgroups[i].items).call(e,(function(t){new Date(t.data.start)new Date(o)&&(o=e)})),t.subgroups[i].start=r,t.subgroups[i].end=new Date(o-1)};for(var i in t.subgroups)e()}}},{key:"orderSubgroups",value:function(){if(void 0!==this.subgroupOrderer){var t=[];if("string"==typeof this.subgroupOrderer){for(var e in this.subgroups)t.push({subgroup:e,sortField:this.subgroups[e].items[0].data[this.subgroupOrderer]});_T(t).call(t,(function(t,e){return t.sortField-e.sortField}))}else if("function"==typeof this.subgroupOrderer){for(var i in this.subgroups)t.push(this.subgroups[i].items[0].data);_T(t).call(t,this.subgroupOrderer)}if(t.length>0)for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:t.data.subgroup;if(null!=e){var i=this.subgroups[e];if(i){var n,r,o=av(n=i.items).call(n,t);if(o>=0)_f(r=i.items).call(r,o,1),i.items.length?this._updateSubgroupsSizes():delete this.subgroups[e]}}}},{key:"removeFromDataSet",value:function(t){this.itemSet.removeItem(t.id)}},{key:"order",value:function(){for(var t=wE.toArray(this.items),e=[],i=[],n=0;n0)for(var u=0;uh})),1==this.checkRangedItems){this.checkRangedItems=!1;for(var c=0;ch}))}for(var f={},m=0,v=0;v0)for(var y=function(t){Hp(wE).call(wE,f,(function(e){e[t]()}))},b=0;b=0;o--){var s=e[o];if(r(s))break;s.isCluster&&!s.hasItems()||s.cluster||void 0===n[s.id]&&(n[s.id]=!0,i.push(s))}for(var a=t+1;a0)for(var o=0;o0)for(var c=0;c=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function xA(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0){var e=[];if(qc(this.options.dataAttributes))e=this.options.dataAttributes;else{if("all"!=this.options.dataAttributes)return;e=rp(this.data)}var i,n=kA(e);try{for(n.s();!(i=n.n()).done;){var r=i.value,o=this.data[r];null!=o?t.setAttribute("data-".concat(r),o):t.removeAttribute("data-".concat(r))}}catch(t){n.e(t)}finally{n.f()}}}},{key:"_updateStyle",value:function(t){this.style&&(wE.removeCssText(t,this.style),this.style=null),this.data.style&&(wE.addCssText(t,this.data.style),this.style=this.data.style)}},{key:"_contentToString",value:function(t){return"string"==typeof t?t:t&&"outerHTML"in t?t.outerHTML:t}},{key:"_updateEditStatus",value:function(){this.options&&("boolean"==typeof this.options.editable?this.editable={updateTime:this.options.editable,updateGroup:this.options.editable,remove:this.options.editable}:"object"===Nd(this.options.editable)&&(this.editable={},wE.selectiveExtend(["updateTime","updateGroup","remove"],this.editable,this.options.editable))),this.options&&this.options.editable&&!0===this.options.editable.overrideItems||this.data&&("boolean"==typeof this.data.editable?this.editable={updateTime:this.data.editable,updateGroup:this.data.editable,remove:this.data.editable}:"object"===Nd(this.data.editable)&&(this.editable={},wE.selectiveExtend(["updateTime","updateGroup","remove"],this.editable,this.data.editable)))}},{key:"getWidthLeft",value:function(){return 0}},{key:"getWidthRight",value:function(){return 0}},{key:"getTitle",value:function(){var t;return this.options.tooltip&&this.options.tooltip.template?Tp(t=this.options.tooltip.template).call(t,this)(this._getItemData(),this.data):this.data.title}}]),t}();function SA(t){var e=function(){if("undefined"==typeof Reflect||!vM)return!1;if(vM.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(vM(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=d_(t);if(e){var r=d_(this).constructor;i=vM(n,arguments,r)}else i=n.apply(this,arguments);return l_(this,i)}}DA.prototype.stack=!0;var CA=function(t){a_(i,t);var e=SA(i);function i(t,n,r){var o;if(Ma(this,i),(o=e.call(this,t,n,r)).props={dot:{width:0,height:0},line:{width:0,height:0}},t&&null==t.start)throw new Error('Property "start" missing in item '.concat(t));return o}return Yd(i,[{key:"isVisible",value:function(t){if(this.cluster)return!1;var e,i=this.data.align||this.options.align,n=this.width*t.getMillisecondsPerPixel();return e="right"==i?this.data.start.getTime()>t.start&&this.data.start.getTime()-nt.start&&this.data.start.getTime()t.start&&this.data.start.getTime()-n/23&&void 0!==arguments[3]&&arguments[3]?-1*e:e;t.style.transform=void 0!==i?void 0!==e?Yc(n="translate(".concat(r,"px, ")).call(n,i,"px)"):"translateY(".concat(i,"px)"):"translateX(".concat(r,"px)")}};e(this.dom.box,this.boxX,this.boxY,t),e(this.dom.dot,this.dotX,this.dotY,t),e(this.dom.line,this.lineX,this.lineY,t)}},{key:"repositionX",value:function(){var t=this.conversion.toScreen(this.data.start),e=void 0===this.data.align?this.options.align:this.data.align,i=this.props.line.width,n=this.props.dot.width;"right"==e?(this.boxX=t-this.width,this.lineX=t-i,this.dotX=t-i/2-n/2):"left"==e?(this.boxX=t,this.lineX=t,this.dotX=t+i/2-n/2):(this.boxX=t-this.width/2,this.lineX=this.options.rtl?t-i:t-i/2,this.dotX=t-n/2),this.options.rtl?this.right=this.boxX:this.left=this.boxX,this.repositionXY()}},{key:"repositionY",value:function(){var t=this.options.orientation.item,e=this.dom.line.style;if("top"==t){var i=this.parent.top+this.top+1;this.boxY=this.top||0,e.height="".concat(i,"px"),e.bottom="",e.top="0"}else{var n=this.parent.itemSet.props.height-this.parent.top-this.parent.height+this.top;this.boxY=this.parent.height-this.top-(this.height||0),e.height="".concat(n,"px"),e.top="",e.bottom="0"}this.dotY=-this.props.dot.height/2,this.repositionXY()}},{key:"getWidthLeft",value:function(){return this.width/2}},{key:"getWidthRight",value:function(){return this.width/2}}]),i}(DA);function TA(t){var e=function(){if("undefined"==typeof Reflect||!vM)return!1;if(vM.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(vM(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=d_(t);if(e){var r=d_(this).constructor;i=vM(n,arguments,r)}else i=n.apply(this,arguments);return l_(this,i)}}var MA=function(t){a_(i,t);var e=TA(i);function i(t,n,r){var o;if(Ma(this,i),(o=e.call(this,t,n,r)).props={dot:{top:0,width:0,height:0},content:{height:0,marginLeft:0,marginRight:0}},t&&null==t.start)throw new Error('Property "start" missing in item '.concat(t));return o}return Yd(i,[{key:"isVisible",value:function(t){if(this.cluster)return!1;var e=this.width*t.getMillisecondsPerPixel();return this.data.start.getTime()+e>t.start&&this.data.start3&&void 0!==arguments[3]&&arguments[3]?-1*e:e;t.style.transform=void 0!==i?void 0!==e?Yc(n="translate(".concat(r,"px, ")).call(n,i,"px)"):"translateY(".concat(i,"px)"):"translateX(".concat(r,"px)")}};e(this.dom.point,this.pointX,this.pointY,t)}},{key:"show",value:function(t){if(!this.displayed)return this.redraw(t)}},{key:"hide",value:function(){this.displayed&&(this.dom.point.parentNode&&this.dom.point.parentNode.removeChild(this.dom.point),this.displayed=!1)}},{key:"repositionX",value:function(){var t=this.conversion.toScreen(this.data.start);this.pointX=t,this.options.rtl?this.right=t-this.props.dot.width:this.left=t-this.props.dot.width,this.repositionXY()}},{key:"repositionY",value:function(){var t=this.options.orientation.item;this.pointY="top"==t?this.top:this.parent.height-this.top-this.height,this.repositionXY()}},{key:"getWidthLeft",value:function(){return this.props.dot.width}},{key:"getWidthRight",value:function(){return this.props.dot.width}}]),i}(DA);function OA(t){var e=function(){if("undefined"==typeof Reflect||!vM)return!1;if(vM.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(vM(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=d_(t);if(e){var r=d_(this).constructor;i=vM(n,arguments,r)}else i=n.apply(this,arguments);return l_(this,i)}}var EA=function(t){a_(i,t);var e=OA(i);function i(t,n,r){var o;if(Ma(this,i),(o=e.call(this,t,n,r)).props={content:{width:0}},o.overflow=!1,t){if(null==t.start)throw new Error('Property "start" missing in item '.concat(t.id));if(null==t.end)throw new Error('Property "end" missing in item '.concat(t.id))}return o}return Yd(i,[{key:"isVisible",value:function(t){return!this.cluster&&(this.data.startt.start)}},{key:"_createDomElement",value:function(){this.dom||(this.dom={},this.dom.box=document.createElement("div"),this.dom.frame=document.createElement("div"),this.dom.frame.className="vis-item-overflow",this.dom.box.appendChild(this.dom.frame),this.dom.visibleFrame=document.createElement("div"),this.dom.visibleFrame.className="vis-item-visible-frame",this.dom.box.appendChild(this.dom.visibleFrame),this.dom.content=document.createElement("div"),this.dom.content.className="vis-item-content",this.dom.frame.appendChild(this.dom.content),this.dom.box["vis-item"]=this,this.dirty=!0)}},{key:"_appendDomElement",value:function(){if(!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!this.dom.box.parentNode){var t=this.parent.dom.foreground;if(!t)throw new Error("Cannot redraw item: parent has no foreground container element");t.appendChild(this.dom.box)}this.displayed=!0}},{key:"_updateDirtyDomComponents",value:function(){if(this.dirty){this._updateContents(this.dom.content),this._updateDataAttributes(this.dom.box),this._updateStyle(this.dom.box);var t=this.editable.updateTime||this.editable.updateGroup,e=(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"")+(t?" vis-editable":" vis-readonly");this.dom.box.className=this.baseClassName+e,this.dom.content.style.maxWidth="none"}}},{key:"_getDomComponentsSizes",value:function(){return this.overflow="hidden"!==window.getComputedStyle(this.dom.frame).overflow,this.whiteSpace="nowrap"!==window.getComputedStyle(this.dom.content).whiteSpace,{content:{width:this.dom.content.offsetWidth},box:{height:this.dom.box.offsetHeight}}}},{key:"_updateDomComponentsSizes",value:function(t){this.props.content.width=t.content.width,this.height=t.box.height,this.dom.content.style.maxWidth="",this.dirty=!1}},{key:"_repaintDomAdditionals",value:function(){this._repaintOnItemUpdateTimeTooltip(this.dom.box),this._repaintDeleteButton(this.dom.box),this._repaintDragCenter(),this._repaintDragLeft(),this._repaintDragRight()}},{key:"redraw",value:function(t){var e,i,n,r,o,s,a=this,l=[Tp(e=this._createDomElement).call(e,this),Tp(i=this._appendDomElement).call(i,this),Tp(n=this._updateDirtyDomComponents).call(n,this),function(){var t;a.dirty&&(o=Tp(t=a._getDomComponentsSizes).call(t,a)())},function(){var t;a.dirty&&Tp(t=a._updateDomComponentsSizes).call(t,a)(o)},Tp(r=this._repaintDomAdditionals).call(r,this)];return t?l:(Hp(l).call(l,(function(t){s=t()})),s)}},{key:"show",value:function(t){if(!this.displayed)return this.redraw(t)}},{key:"hide",value:function(){if(this.displayed){var t=this.dom.box;t.parentNode&&t.parentNode.removeChild(t),this.displayed=!1}}},{key:"repositionX",value:function(t){var e,i,n=this.parent.width,r=this.conversion.toScreen(this.data.start),o=this.conversion.toScreen(this.data.end),s=void 0===this.data.align?this.options.align:this.data.align;!1===this.data.limitSize||void 0!==t&&!0!==t||(r<-n&&(r=-n),o>2*n&&(o=2*n));var a=Math.max(Math.round(1e3*(o-r))/1e3,1);switch(this.overflow?(this.options.rtl?this.right=r:this.left=r,this.width=a+this.props.content.width,i=this.props.content.width):(this.options.rtl?this.right=r:this.left=r,this.width=a,i=Math.min(o-r,this.props.content.width)),this.options.rtl?this.dom.box.style.transform="translateX(".concat(-1*this.right,"px)"):this.dom.box.style.transform="translateX(".concat(this.left,"px)"),this.dom.box.style.width="".concat(a,"px"),this.whiteSpace&&(this.height=this.dom.box.offsetHeight),s){case"left":this.dom.content.style.transform="translateX(0)";break;case"right":if(this.options.rtl){var l=-1*Math.max(a-i,0);this.dom.content.style.transform="translateX(".concat(l,"px)")}else this.dom.content.style.transform="translateX(".concat(Math.max(a-i,0),"px)");break;case"center":if(this.options.rtl){var h=-1*Math.max((a-i)/2,0);this.dom.content.style.transform="translateX(".concat(h,"px)")}else this.dom.content.style.transform="translateX(".concat(Math.max((a-i)/2,0),"px)");break;default:if(e=this.overflow?o>0?Math.max(-r,0):-i:r<0?-r:0,this.options.rtl){var u=-1*e;this.dom.content.style.transform="translateX(".concat(u,"px)")}else this.dom.content.style.transform="translateX(".concat(e,"px)")}}},{key:"repositionY",value:function(){var t=this.options.orientation.item,e=this.dom.box;e.style.top="".concat("top"==t?this.top:this.parent.height-this.top-this.height,"px")}},{key:"_repaintDragLeft",value:function(){if((this.selected||this.options.itemsAlwaysDraggable.range)&&this.editable.updateTime&&!this.dom.dragLeft){var t=document.createElement("div");t.className="vis-drag-left",t.dragLeftItem=this,this.dom.box.appendChild(t),this.dom.dragLeft=t}else this.selected||this.options.itemsAlwaysDraggable.range||!this.dom.dragLeft||(this.dom.dragLeft.parentNode&&this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft),this.dom.dragLeft=null)}},{key:"_repaintDragRight",value:function(){if((this.selected||this.options.itemsAlwaysDraggable.range)&&this.editable.updateTime&&!this.dom.dragRight){var t=document.createElement("div");t.className="vis-drag-right",t.dragRightItem=this,this.dom.box.appendChild(t),this.dom.dragRight=t}else this.selected||this.options.itemsAlwaysDraggable.range||!this.dom.dragRight||(this.dom.dragRight.parentNode&&this.dom.dragRight.parentNode.removeChild(this.dom.dragRight),this.dom.dragRight=null)}}]),i}(DA);function PA(t){var e=function(){if("undefined"==typeof Reflect||!vM)return!1;if(vM.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(vM(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=d_(t);if(e){var r=d_(this).constructor;i=vM(n,arguments,r)}else i=n.apply(this,arguments);return l_(this,i)}}EA.prototype.baseClassName="vis-item vis-range";var AA=function(t){a_(i,t);var e=PA(i);function i(t,n,r){var o;if(Ma(this,i),(o=e.call(this,t,n,r)).props={content:{width:0}},o.overflow=!1,t){if(null==t.start)throw new Error('Property "start" missing in item '.concat(t.id));if(null==t.end)throw new Error('Property "end" missing in item '.concat(t.id))}return o}return Yd(i,[{key:"isVisible",value:function(t){return this.data.startt.start}},{key:"_createDomElement",value:function(){this.dom||(this.dom={},this.dom.box=document.createElement("div"),this.dom.frame=document.createElement("div"),this.dom.frame.className="vis-item-overflow",this.dom.box.appendChild(this.dom.frame),this.dom.content=document.createElement("div"),this.dom.content.className="vis-item-content",this.dom.frame.appendChild(this.dom.content),this.dirty=!0)}},{key:"_appendDomElement",value:function(){if(!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!this.dom.box.parentNode){var t=this.parent.dom.background;if(!t)throw new Error("Cannot redraw item: parent has no background container element");t.appendChild(this.dom.box)}this.displayed=!0}},{key:"_updateDirtyDomComponents",value:function(){if(this.dirty){this._updateContents(this.dom.content),this._updateDataAttributes(this.dom.content),this._updateStyle(this.dom.box);var t=(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"");this.dom.box.className=this.baseClassName+t}}},{key:"_getDomComponentsSizes",value:function(){return this.overflow="hidden"!==window.getComputedStyle(this.dom.content).overflow,{content:{width:this.dom.content.offsetWidth}}}},{key:"_updateDomComponentsSizes",value:function(t){this.props.content.width=t.content.width,this.height=0,this.dirty=!1}},{key:"_repaintDomAdditionals",value:function(){}},{key:"redraw",value:function(t){var e,i,n,r,o,s,a=this,l=[Tp(e=this._createDomElement).call(e,this),Tp(i=this._appendDomElement).call(i,this),Tp(n=this._updateDirtyDomComponents).call(n,this),function(){var t;a.dirty&&(o=Tp(t=a._getDomComponentsSizes).call(t,a)())},function(){var t;a.dirty&&Tp(t=a._updateDomComponentsSizes).call(t,a)(o)},Tp(r=this._repaintDomAdditionals).call(r,this)];return t?l:(Hp(l).call(l,(function(t){s=t()})),s)}},{key:"repositionY",value:function(t){var e,i=this.options.orientation.item;if(void 0!==this.data.subgroup){var n=this.data.subgroup;this.dom.box.style.height="".concat(this.parent.subgroups[n].height,"px"),this.dom.box.style.top="".concat("top"==i?this.parent.top+this.parent.subgroups[n].top:this.parent.top+this.parent.height-this.parent.subgroups[n].top-this.parent.subgroups[n].height,"px"),this.dom.box.style.bottom=""}else this.parent instanceof wA?(e=Math.max(this.parent.height,this.parent.itemSet.body.domProps.center.height,this.parent.itemSet.body.domProps.centerContainer.height),this.dom.box.style.bottom="bottom"==i?"0":"",this.dom.box.style.top="top"==i?"0":""):(e=this.parent.height,this.dom.box.style.top="".concat(this.parent.top,"px"),this.dom.box.style.bottom="");this.dom.box.style.height="".concat(e,"px")}}]),i}(DA);AA.prototype.baseClassName="vis-item vis-background",AA.prototype.stack=!1,AA.prototype.show=EA.prototype.show,AA.prototype.hide=EA.prototype.hide,AA.prototype.repositionX=EA.prototype.repositionX;pP("div.vis-tooltip{background-color:#f5f4ed;border:1px solid #808074;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;box-shadow:3px 3px 10px rgba(0,0,0,.2);color:#000;font-family:verdana;font-size:14px;padding:5px;pointer-events:none;position:absolute;visibility:hidden;white-space:nowrap;z-index:5}");var IA=function(){function t(e,i){Ma(this,t),this.container=e,this.overflowMethod=i||"cap",this.x=0,this.y=0,this.padding=5,this.hidden=!1,this.frame=document.createElement("div"),this.frame.className="vis-tooltip",this.container.appendChild(this.frame)}return Yd(t,[{key:"setPosition",value:function(t,e){this.x=Zm(t),this.y=Zm(e)}},{key:"setText",value:function(t){t instanceof Element?(this.frame.innerHTML="",this.frame.appendChild(t)):this.frame.innerHTML=wE.xss(t)}},{key:"show",value:function(t){if(void 0===t&&(t=!0),!0===t){var e=this.frame.clientHeight,i=this.frame.clientWidth,n=this.frame.parentNode.clientHeight,r=this.frame.parentNode.clientWidth,o=0,s=0;if("flip"==this.overflowMethod||"none"==this.overflowMethod){var a=!1,l=!0;"flip"==this.overflowMethod&&(this.y-er-this.padding&&(a=!0)),o=a?this.x-i:this.x,s=l?this.y-e:this.y}else(s=this.y-e)+e+this.padding>n&&(s=n-e-this.padding),sr&&(o=r-i-this.padding),o1?arguments[1]:void 0)}});var NA=Jd("Array").every,RA=ye,FA=NA,jA=Array.prototype,YA=function(t){var e=t.every;return t===jA||RA(jA,t)&&e===jA.every?FA:e},HA=n(YA);function zA(t,e){var i=void 0!==Ic&&Ta(t)||t["@@iterator"];if(!i){if(qc(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return BA(t,e);var n=Hc(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return sa(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return BA(t,e)}(t))||e&&t&&"number"==typeof t.length){i&&(t=i);var n=0,r=function(){};return{s:r,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function BA(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);it.start&&this.hasItems()}},{key:"getData",value:function(){return{isCluster:!0,id:this.id,items:this.data.items||[],data:this.data}}},{key:"redraw",value:function(t){var e,i,n,r,o,s,a,l,h=[Tp(e=this._createDomElement).call(e,this),Tp(i=this._appendDomElement).call(i,this),Tp(n=this._updateDirtyDomComponents).call(n,this),Tp(r=function(){this.dirty&&(a=this._getDomComponentsSizes())}).call(r,this),Tp(o=function(){var t;this.dirty&&Tp(t=this._updateDomComponentsSizes).call(t,this)(a)}).call(o,this),Tp(s=this._repaintDomAdditionals).call(s,this)];return t?h:(Hp(h).call(h,(function(t){l=t()})),l)}},{key:"show",value:function(){this.displayed||this.redraw()}},{key:"hide",value:function(){if(this.displayed){var t=this.dom;t.box.parentNode&&t.box.parentNode.removeChild(t.box),this.options.showStipes&&(t.line.parentNode&&t.line.parentNode.removeChild(t.line),t.dot.parentNode&&t.dot.parentNode.removeChild(t.dot)),this.displayed=!1}}},{key:"repositionX",value:function(){var t=this.conversion.toScreen(this.data.start),e=this.data.end?this.conversion.toScreen(this.data.end):0;if(e)this.repositionXWithRanges(t,e);else{var i=void 0===this.data.align?this.options.align:this.data.align;this.repositionXWithoutRanges(t,i)}this.options.showStipes&&(this.dom.line.style.display=this._isStipeVisible()?"block":"none",this.dom.dot.style.display=this._isStipeVisible()?"block":"none",this._isStipeVisible()&&this.repositionStype(t,e))}},{key:"repositionStype",value:function(t,e){this.dom.line.style.display="block",this.dom.dot.style.display="block";var i=this.dom.line.offsetWidth,n=this.dom.dot.offsetWidth;if(e){var r=i+t+(e-t)/2,o=r-n/2,s=this.options.rtl?-1*r:r,a=this.options.rtl?-1*o:o;this.dom.line.style.transform="translateX(".concat(s,"px)"),this.dom.dot.style.transform="translateX(".concat(a,"px)")}else{var l=this.options.rtl?-1*t:t,h=this.options.rtl?-1*(t-n/2):t-n/2;this.dom.line.style.transform="translateX(".concat(l,"px)"),this.dom.dot.style.transform="translateX(".concat(h,"px)")}}},{key:"repositionXWithoutRanges",value:function(t,e){"right"==e?this.options.rtl?(this.right=t-this.width,this.dom.box.style.right=this.right+"px"):(this.left=t-this.width,this.dom.box.style.left=this.left+"px"):"left"==e?this.options.rtl?(this.right=t,this.dom.box.style.right=this.right+"px"):(this.left=t,this.dom.box.style.left=this.left+"px"):this.options.rtl?(this.right=t-this.width/2,this.dom.box.style.right=this.right+"px"):(this.left=t-this.width/2,this.dom.box.style.left=this.left+"px")}},{key:"repositionXWithRanges",value:function(t,e){var i=Math.round(Math.max(e-t+.5,1));this.options.rtl?this.right=t:this.left=t,this.width=Math.max(i,this.minWidth||0),this.options.rtl?this.dom.box.style.right=this.right+"px":this.dom.box.style.left=this.left+"px",this.dom.box.style.width=i+"px"}},{key:"repositionY",value:function(){var t=this.options.orientation.item,e=this.dom.box;if(e.style.top="top"==t?(this.top||0)+"px":(this.parent.height-this.top-this.height||0)+"px",this.options.showStipes){if("top"==t)this.dom.line.style.top="0",this.dom.line.style.height=this.parent.top+this.top+1+"px",this.dom.line.style.bottom="";else{var i=this.parent.itemSet.props.height,n=i-this.parent.top-this.parent.height+this.top;this.dom.line.style.top=i-n+"px",this.dom.line.style.bottom="0"}this.dom.dot.style.top=-this.dom.dot.offsetHeight/2+"px"}}},{key:"getWidthLeft",value:function(){return this.width/2}},{key:"getWidthRight",value:function(){return this.width/2}},{key:"move",value:function(){this.repositionX(),this.repositionY()}},{key:"attach",value:function(){var t,e,i=zA(this.data.uiItems);try{for(i.s();!(e=i.n()).done;){e.value.cluster=this}}catch(t){i.e(t)}finally{i.f()}this.data.items=ep(t=this.data.uiItems).call(t,(function(t){return t.data})),this.attached=!0,this.dirty=!0}},{key:"detach",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(this.hasItems()){var e,i=zA(this.data.uiItems);try{for(i.s();!(e=i.n()).done;){delete e.value.cluster}}catch(t){i.e(t)}finally{i.f()}this.attached=!1,t&&this.group&&(this.group.remove(this),this.group=null),this.data.items=[],this.dirty=!0}}},{key:"_onDoubleClick",value:function(){this._fit()}},{key:"_setupRange",value:function(){var t,e,i,n=ep(t=this.data.uiItems).call(t,(function(t){return{start:t.data.start.valueOf(),end:t.data.end?t.data.end.valueOf():t.data.start.valueOf()}}));this.data.min=Math.min.apply(Math,Ac(ep(n).call(n,(function(t){return Math.min(t.start,t.end||t.start)})))),this.data.max=Math.max.apply(Math,Ac(ep(n).call(n,(function(t){return Math.max(t.start,t.end||t.start)}))));var r=ep(e=this.data.uiItems).call(e,(function(t){return t.center})),o=cS(r).call(r,(function(t,e){return t+e}),0)/this.data.uiItems.length;TT(i=this.data.uiItems).call(i,(function(t){return t.data.end}))?(this.data.start=new Date(this.data.min),this.data.end=new Date(this.data.max)):(this.data.start=new Date(o),this.data.end=null)}},{key:"_getUiItems",value:function(){var t,e=this;return this.data.uiItems&&this.data.uiItems.length?mm(t=this.data.uiItems).call(t,(function(t){return t.cluster===e})):[]}},{key:"_createDomElement",value:function(){if(!this.dom){var t;if(this.dom={},this.dom.box=document.createElement("DIV"),this.dom.content=document.createElement("DIV"),this.dom.content.className="vis-item-content",this.dom.box.appendChild(this.dom.content),this.options.showStipes&&(this.dom.line=document.createElement("DIV"),this.dom.line.className="vis-cluster-line",this.dom.line.style.display="none",this.dom.dot=document.createElement("DIV"),this.dom.dot.className="vis-cluster-dot",this.dom.dot.style.display="none"),this.options.fitOnDoubleClick)this.dom.box.ondblclick=Tp(t=i.prototype._onDoubleClick).call(t,this);this.dom.box["vis-item"]=this,this.dirty=!0}}},{key:"_appendDomElement",value:function(){if(!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!this.dom.box.parentNode){var t=this.parent.dom.foreground;if(!t)throw new Error("Cannot redraw item: parent has no foreground container element");t.appendChild(this.dom.box)}var e=this.parent.dom.background;if(this.options.showStipes){if(!this.dom.line.parentNode){if(!e)throw new Error("Cannot redraw item: parent has no background container element");e.appendChild(this.dom.line)}if(!this.dom.dot.parentNode){var i=this.parent.dom.axis;if(!e)throw new Error("Cannot redraw item: parent has no axis container element");i.appendChild(this.dom.dot)}}this.displayed=!0}},{key:"_updateDirtyDomComponents",value:function(){if(this.dirty){this._updateContents(this.dom.content),this._updateDataAttributes(this.dom.box),this._updateStyle(this.dom.box);var t=this.baseClassName+" "+(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"")+" vis-readonly";this.dom.box.className="vis-item "+t,this.options.showStipes&&(this.dom.line.className="vis-item vis-cluster-line "+(this.selected?" vis-selected":""),this.dom.dot.className="vis-item vis-cluster-dot "+(this.selected?" vis-selected":"")),this.data.end&&(this.dom.content.style.maxWidth="none")}}},{key:"_getDomComponentsSizes",value:function(){var t={previous:{right:this.dom.box.style.right,left:this.dom.box.style.left},box:{width:this.dom.box.offsetWidth,height:this.dom.box.offsetHeight}};return this.options.showStipes&&(t.dot={height:this.dom.dot.offsetHeight,width:this.dom.dot.offsetWidth},t.line={width:this.dom.line.offsetWidth}),t}},{key:"_updateDomComponentsSizes",value:function(t){this.options.rtl?this.dom.box.style.right="0px":this.dom.box.style.left="0px",this.data.end?this.minWidth=t.box.width:this.width=t.box.width,this.height=t.box.height,this.options.rtl?this.dom.box.style.right=t.previous.right:this.dom.box.style.left=t.previous.left,this.dirty=!1}},{key:"_repaintDomAdditionals",value:function(){this._repaintOnItemUpdateTimeTooltip(this.dom.box)}},{key:"_isStipeVisible",value:function(){return this.minWidth>=this.width||!this.data.end}},{key:"_getFitRange",value:function(){var t=.05*(this.data.max-this.data.min)/2;return{fitStart:this.data.min-t,fitEnd:this.data.max+t}}},{key:"_fit",value:function(){if(this.emitter){var t=this._getFitRange(),e=t.fitStart,i=t.fitEnd,n={start:new Date(e),end:new Date(i),animation:!0};this.emitter.emit("fit",n)}}},{key:"_getItemData",value:function(){return this.data}}]),i}(DA);function VA(t,e){var i=void 0!==Ic&&Ta(t)||t["@@iterator"];if(!i){if(qc(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return UA(t,e);var n=Hc(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return sa(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return UA(t,e)}(t))||e&&t&&"number"==typeof t.length){i&&(t=i);var n=0,r=function(){};return{s:r,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function UA(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0){if(e>=1)return[];s=Math.abs(Math.round(Math.log(100/e)/Math.log(2))),a=Math.abs(Math.pow(2,s))}if(this.dataChanged){var l=s!=this.cacheLevel;(!this.applyOnChangedLevel||l)&&(this._dropLevelsCache(),this._filterData())}this.cacheLevel=s;var h=this.cache[s];if(!h){for(var u in h=[],this.groups)if(this.groups.hasOwnProperty(u))for(var d=this.groups[u],c=d.length,p=0;p=0&&f.center-d[v].center=0&&f.center-h[y].centerr){for(var b=m-r+1,_=[],w=p;_.length'+t.length+"",f=Nf({},n,this.itemSet.options),m={content:p,title:c,group:e,uiItems:t,eventEmitter:this.itemSet.body.emitter,range:this.itemSet.body.range};return o=this.createClusterItem(m,d,f),e&&(e.add(o),o.group=e),o.attach(),o}},{key:"_dropLevelsCache",value:function(){this.cache={},this.cacheLevel=-1,this.cache[this.cacheLevel]=[]}}]),t}();pP('.vis-itemset{box-sizing:border-box;margin:0;padding:0;position:relative}.vis-itemset .vis-background,.vis-itemset .vis-foreground{height:100%;overflow:visible;position:absolute;width:100%}.vis-axis{height:0;left:0;position:absolute;width:100%;z-index:1}.vis-foreground .vis-group{border-bottom:1px solid #bfbfbf;box-sizing:border-box;position:relative}.vis-foreground .vis-group:last-child{border-bottom:none}.vis-nesting-group{cursor:pointer}.vis-label.vis-nested-group.vis-group-level-unknown-but-gte1{background:#f5f5f5}.vis-label.vis-nested-group.vis-group-level-0{background-color:#fff}.vis-ltr .vis-label.vis-nested-group.vis-group-level-0 .vis-inner{padding-left:0}.vis-rtl .vis-label.vis-nested-group.vis-group-level-0 .vis-inner{padding-right:0}.vis-label.vis-nested-group.vis-group-level-1{background-color:rgba(0,0,0,.05)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-1 .vis-inner{padding-left:15px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-1 .vis-inner{padding-right:15px}.vis-label.vis-nested-group.vis-group-level-2{background-color:rgba(0,0,0,.1)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-2 .vis-inner{padding-left:30px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-2 .vis-inner{padding-right:30px}.vis-label.vis-nested-group.vis-group-level-3{background-color:rgba(0,0,0,.15)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-3 .vis-inner{padding-left:45px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-3 .vis-inner{padding-right:45px}.vis-label.vis-nested-group.vis-group-level-4{background-color:rgba(0,0,0,.2)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-4 .vis-inner{padding-left:60px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-4 .vis-inner{padding-right:60px}.vis-label.vis-nested-group.vis-group-level-5{background-color:rgba(0,0,0,.25)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-5 .vis-inner{padding-left:75px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-5 .vis-inner{padding-right:75px}.vis-label.vis-nested-group.vis-group-level-6{background-color:rgba(0,0,0,.3)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-6 .vis-inner{padding-left:90px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-6 .vis-inner{padding-right:90px}.vis-label.vis-nested-group.vis-group-level-7{background-color:rgba(0,0,0,.35)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-7 .vis-inner{padding-left:105px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-7 .vis-inner{padding-right:105px}.vis-label.vis-nested-group.vis-group-level-8{background-color:rgba(0,0,0,.4)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-8 .vis-inner{padding-left:120px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-8 .vis-inner{padding-right:120px}.vis-label.vis-nested-group.vis-group-level-9{background-color:rgba(0,0,0,.45)}.vis-ltr .vis-label.vis-nested-group.vis-group-level-9 .vis-inner{padding-left:135px}.vis-rtl .vis-label.vis-nested-group.vis-group-level-9 .vis-inner{padding-right:135px}.vis-label.vis-nested-group{background-color:rgba(0,0,0,.5)}.vis-ltr .vis-label.vis-nested-group .vis-inner{padding-left:150px}.vis-rtl .vis-label.vis-nested-group .vis-inner{padding-right:150px}.vis-group-level-unknown-but-gte1{border:1px solid red}.vis-label.vis-nesting-group:before{display:inline-block;width:15px}.vis-label.vis-nesting-group.expanded:before{content:"\\25BC"}.vis-label.vis-nesting-group.collapsed:before{content:"\\25B6"}.vis-rtl .vis-label.vis-nesting-group.collapsed:before{content:"\\25C0"}.vis-ltr .vis-label:not(.vis-nesting-group):not(.vis-group-level-0){padding-left:15px}.vis-rtl .vis-label:not(.vis-nesting-group):not(.vis-group-level-0){padding-right:15px}.vis-overlay{height:100%;left:0;position:absolute;top:0;width:100%;z-index:10}');function $A(t,e){var i=void 0!==Ic&&Ta(t)||t["@@iterator"];if(!i){if(qc(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return ZA(t,e);var n=Hc(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return sa(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ZA(t,e)}(t))||e&&t&&"number"==typeof t.length){i&&(t=i);var n=0,r=function(){};return{s:r,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function ZA(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0){var n,r=o.groupsData.getDataSet();Hp(n=r.get()).call(n,(function(t){if(t.nestedGroups){var e;0!=t.showNested&&(t.showNested=!0);var n=[];Hp(e=t.nestedGroups).call(e,(function(e){var i=r.get(e);i&&(i.nestedInGroup=t.id,0==t.showNested&&(i.visible=!1),n=Yc(n).call(n,i))})),r.update(n,i)}}))}},update:function(t,e,i){o._onUpdateGroups(e.items)},remove:function(t,e,i){o._onRemoveGroups(e.items)}},r.items={},r.groups={},r.groupIds=[],r.selection=[],r.popup=null,r.popupTimer=null,r.touchParams={},r.groupTouchParams={group:null,isDragging:!1},r._create(),r.setOptions(n),r.clusters=[],r}return Yd(i,[{key:"_create",value:function(){var t,e,i,n,r,o,s,a,l,h,u,d,c,p,f,m=this,v=document.createElement("div");v.className="vis-itemset",v["vis-itemset"]=this,this.dom.frame=v;var g=document.createElement("div");g.className="vis-background",v.appendChild(g),this.dom.background=g;var y=document.createElement("div");y.className="vis-foreground",v.appendChild(y),this.dom.foreground=y;var b=document.createElement("div");b.className="vis-axis",this.dom.axis=b;var _=document.createElement("div");_.className="vis-labelset",this.dom.labelSet=_,this._updateUngrouped();var w=new wA(QA,null,this);w.show(),this.groups[QA]=w,this.hammer=new uP(this.body.dom.centerContainer),this.hammer.on("hammer.input",(function(t){t.isFirst&&m._onTouch(t)})),this.hammer.on("panstart",Tp(t=this._onDragStart).call(t,this)),this.hammer.on("panmove",Tp(e=this._onDrag).call(e,this)),this.hammer.on("panend",Tp(i=this._onDragEnd).call(i,this)),this.hammer.get("pan").set({threshold:5,direction:uP.ALL}),this.hammer.get("press").set({time:1e4}),this.hammer.on("tap",Tp(n=this._onSelectItem).call(n,this)),this.hammer.on("press",Tp(r=this._onMultiSelectItem).call(r,this)),this.hammer.get("press").set({time:1e4}),this.hammer.on("doubletap",Tp(o=this._onAddItem).call(o,this)),this.options.rtl?this.groupHammer=new uP(this.body.dom.rightContainer):this.groupHammer=new uP(this.body.dom.leftContainer),this.groupHammer.on("tap",Tp(s=this._onGroupClick).call(s,this)),this.groupHammer.on("panstart",Tp(a=this._onGroupDragStart).call(a,this)),this.groupHammer.on("panmove",Tp(l=this._onGroupDrag).call(l,this)),this.groupHammer.on("panend",Tp(h=this._onGroupDragEnd).call(h,this)),this.groupHammer.get("pan").set({threshold:5,direction:uP.DIRECTION_VERTICAL}),this.body.dom.centerContainer.addEventListener("mouseover",Tp(u=this._onMouseOver).call(u,this)),this.body.dom.centerContainer.addEventListener("mouseout",Tp(d=this._onMouseOut).call(d,this)),this.body.dom.centerContainer.addEventListener("mousemove",Tp(c=this._onMouseMove).call(c,this)),this.body.dom.centerContainer.addEventListener("contextmenu",Tp(p=this._onDragEnd).call(p,this)),this.body.dom.centerContainer.addEventListener("mousewheel",Tp(f=this._onMouseWheel).call(f,this)),this.show()}},{key:"setOptions",value:function(t){var e=this;if(t){var i,n;wE.selectiveExtend(["type","rtl","align","order","stack","stackSubgroups","selectable","multiselect","sequentialSelection","multiselectPerGroup","longSelectPressTime","groupOrder","dataAttributes","template","groupTemplate","visibleFrameTemplate","hide","snap","groupOrderSwap","showTooltips","tooltip","tooltipOnItemUpdateTime","groupHeightMode","onTimeout"],this.options,t),"itemsAlwaysDraggable"in t&&("boolean"==typeof t.itemsAlwaysDraggable?(this.options.itemsAlwaysDraggable.item=t.itemsAlwaysDraggable,this.options.itemsAlwaysDraggable.range=!1):"object"===Nd(t.itemsAlwaysDraggable)&&(wE.selectiveExtend(["item","range"],this.options.itemsAlwaysDraggable,t.itemsAlwaysDraggable),this.options.itemsAlwaysDraggable.item||(this.options.itemsAlwaysDraggable.range=!1))),"sequentialSelection"in t&&"boolean"==typeof t.sequentialSelection&&(this.options.sequentialSelection=t.sequentialSelection),"orientation"in t&&("string"==typeof t.orientation?this.options.orientation.item="top"===t.orientation?"top":"bottom":"object"===Nd(t.orientation)&&"item"in t.orientation&&(this.options.orientation.item=t.orientation.item)),"margin"in t&&("number"==typeof t.margin?(this.options.margin.axis=t.margin,this.options.margin.item.horizontal=t.margin,this.options.margin.item.vertical=t.margin):"object"===Nd(t.margin)&&(wE.selectiveExtend(["axis"],this.options.margin,t.margin),"item"in t.margin&&("number"==typeof t.margin.item?(this.options.margin.item.horizontal=t.margin.item,this.options.margin.item.vertical=t.margin.item):"object"===Nd(t.margin.item)&&wE.selectiveExtend(["horizontal","vertical"],this.options.margin.item,t.margin.item)))),Hp(i=["locale","locales"]).call(i,(function(i){i in t&&(e.options[i]=t[i])})),"editable"in t&&("boolean"==typeof t.editable?(this.options.editable.updateTime=t.editable,this.options.editable.updateGroup=t.editable,this.options.editable.add=t.editable,this.options.editable.remove=t.editable,this.options.editable.overrideItems=!1):"object"===Nd(t.editable)&&wE.selectiveExtend(["updateTime","updateGroup","add","remove","overrideItems"],this.options.editable,t.editable)),"groupEditable"in t&&("boolean"==typeof t.groupEditable?(this.options.groupEditable.order=t.groupEditable,this.options.groupEditable.add=t.groupEditable,this.options.groupEditable.remove=t.groupEditable):"object"===Nd(t.groupEditable)&&wE.selectiveExtend(["order","add","remove"],this.options.groupEditable,t.groupEditable));Hp(n=["onDropObjectOnItem","onAdd","onUpdate","onRemove","onMove","onMoving","onAddGroup","onMoveGroup","onRemoveGroup"]).call(n,(function(i){var n=t[i];if(n){var r;if("function"!=typeof n)throw new Error(Yc(r="option ".concat(i," must be a function ")).call(r,i,"(item, callback)"));e.options[i]=n}})),t.cluster?(Nf(this.options,{cluster:t.cluster}),this.clusterGenerator||(this.clusterGenerator=new qA(this)),this.clusterGenerator.setItems(this.items,{applyOnChangedLevel:!1}),this.markDirty({refreshItems:!0,restackGroups:!0}),this.redraw()):this.clusterGenerator?(this._detachAllClusters(),this.clusters=[],this.clusterGenerator=null,this.options.cluster=void 0,this.markDirty({refreshItems:!0,restackGroups:!0}),this.redraw()):this.markDirty()}}},{key:"markDirty",value:function(t){this.groupIds=[],t&&(t.refreshItems&&Hp(wE).call(wE,this.items,(function(t){t.dirty=!0,t.displayed&&t.redraw()})),t.restackGroups&&Hp(wE).call(wE,this.groups,(function(t,e){e!==QA&&(t.stackDirty=!0)})))}},{key:"destroy",value:function(){this.clearPopupTimer(),this.hide(),this.setItems(null),this.setGroups(null),this.hammer&&this.hammer.destroy(),this.groupHammer&&this.groupHammer.destroy(),this.hammer=null,this.body=null,this.conversion=null}},{key:"hide",value:function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame),this.dom.axis.parentNode&&this.dom.axis.parentNode.removeChild(this.dom.axis),this.dom.labelSet.parentNode&&this.dom.labelSet.parentNode.removeChild(this.dom.labelSet)}},{key:"show",value:function(){this.dom.frame.parentNode||this.body.dom.center.appendChild(this.dom.frame),this.dom.axis.parentNode||this.body.dom.backgroundVertical.appendChild(this.dom.axis),this.dom.labelSet.parentNode||(this.options.rtl?this.body.dom.right.appendChild(this.dom.labelSet):this.body.dom.left.appendChild(this.dom.labelSet))}},{key:"setPopupTimer",value:function(t){if(this.clearPopupTimer(),t){var e=this.options.tooltip.delay||"number"==typeof this.options.tooltip.delay?this.options.tooltip.delay:500;this.popupTimer=Rv((function(){t.show()}),e)}}},{key:"clearPopupTimer",value:function(){null!=this.popupTimer&&(clearTimeout(this.popupTimer),this.popupTimer=null)}},{key:"setSelection",value:function(t){var e;null==t&&(t=[]),qc(t)||(t=[t]);var i,n=mm(e=this.selection).call(e,(function(e){return-1===av(t).call(t,e)})),r=$A(n);try{for(r.s();!(i=r.n()).done;){var o=i.value,s=this.getItemById(o);s&&s.unselect()}}catch(t){r.e(t)}finally{r.f()}this.selection=Ac(t);var a,l=$A(t);try{for(l.s();!(a=l.n()).done;){var h=a.value,u=this.getItemById(h);u&&u.select()}}catch(t){l.e(t)}finally{l.f()}}},{key:"getSelection",value:function(){var t;return Yc(t=this.selection).call(t,[])}},{key:"getVisibleItems",value:function(){var t,e,i=this.body.range.getRange();this.options.rtl?(t=this.body.util.toScreen(i.start),e=this.body.util.toScreen(i.end)):(e=this.body.util.toScreen(i.start),t=this.body.util.toScreen(i.end));var n=[];for(var r in this.groups)if(this.groups.hasOwnProperty(r)){var o,s=this.groups[r],a=$A(s.isVisible?s.visibleItems:[]);try{for(a.s();!(o=a.n()).done;){var l=o.value;this.options.rtl?l.rightt&&n.push(l.id):l.lefte&&n.push(l.id)}}catch(t){a.e(t)}finally{a.f()}}return n}},{key:"getItemsAtCurrentTime",value:function(t){var e,i;this.options.rtl?(e=this.body.util.toScreen(t),i=this.body.util.toScreen(t)):(i=this.body.util.toScreen(t),e=this.body.util.toScreen(t));var n=[];for(var r in this.groups)if(this.groups.hasOwnProperty(r)){var o,s=this.groups[r],a=$A(s.isVisible?s.visibleItems:[]);try{for(a.s();!(o=a.n()).done;){var l=o.value;this.options.rtl?l.righte&&n.push(l.id):l.lefti&&n.push(l.id)}}catch(t){a.e(t)}finally{a.f()}}return n}},{key:"getVisibleGroups",value:function(){var t=[];for(var e in this.groups){if(this.groups.hasOwnProperty(e))this.groups[e].isVisible&&t.push(e)}return t}},{key:"getItemById",value:function(t){var e;return this.items[t]||qP(e=this.clusters).call(e,(function(e){return e.id===t}))}},{key:"_deselect",value:function(t){for(var e=this.selection,i=0,n=e.length;i0){for(var _={},w=function(t){Hp(wE).call(wE,y,(function(e,i){_[i]=e[t]()}))},k=0;k1&&void 0!==arguments[1]?arguments[1]:void 0;if(t&&t.nestedGroups){var i=this.groupsData.getDataSet();t.showNested=null!=e?!!e:!t.showNested;var n=i.get(t.groupId);n.showNested=t.showNested;for(var r,o=t.nestedGroups,s=o;s.length>0;){var a=s;s=[];for(var l=0;l0&&(o=Yc(o).call(o,s))}if(n.showNested){for(var u=i.get(n.nestedGroups),d=0;d0&&(null==c.showNested||1==c.showNested)&&u.push.apply(u,Ac(i.get(c.nestedGroups)))}r=ep(u).call(u,(function(t){return null==t.visible&&(t.visible=!0),t.visible=!!n.showNested,t}))}else{var p;r=ep(p=i.get(o)).call(p,(function(t){return null==t.visible&&(t.visible=!0),t.visible=!!n.showNested,t}))}i.update(Yc(r).call(r,n)),n.showNested?(wE.removeClassName(t.dom.label,"collapsed"),wE.addClassName(t.dom.label,"expanded")):(wE.removeClassName(t.dom.label,"expanded"),wE.addClassName(t.dom.label,"collapsed"))}}},{key:"toggleGroupDragClassName",value:function(t){t.dom.label.classList.toggle("vis-group-is-dragging"),t.dom.foreground.classList.toggle("vis-group-is-dragging")}},{key:"_onGroupDragStart",value:function(t){this.groupTouchParams.isDragging||this.options.groupEditable.order&&(this.groupTouchParams.group=this.groupFromTarget(t),this.groupTouchParams.group&&(t.stopPropagation(),this.groupTouchParams.isDragging=!0,this.toggleGroupDragClassName(this.groupTouchParams.group),this.groupTouchParams.originalOrder=this.groupsData.getIds({order:this.options.groupOrder})))}},{key:"_onGroupDrag",value:function(t){if(this.options.groupEditable.order&&this.groupTouchParams.group){t.stopPropagation();var e=this.groupsData.getDataSet(),i=this.groupFromTarget(t);if(i&&i.height!=this.groupTouchParams.group.height){var n=i.topr)return}}if(i&&i!=this.groupTouchParams.group){var l=e.get(i.groupId),h=e.get(this.groupTouchParams.group.groupId);h&&l&&(this.options.groupOrderSwap(h,l,e),e.update(h),e.update(l));var u=e.getIds({order:this.options.groupOrder});if(!wE.equalArray(u,this.groupTouchParams.originalOrder))for(var d=this.groupTouchParams.originalOrder,c=this.groupTouchParams.group.groupId,p=Math.min(d.length,u.length),f=0,m=0,v=0;f=p)break;if(u[f+m]==c)m=1;else if(d[f+v]==c)v=1;else{var g=av(u).call(u,d[f+v]),y=e.get(u[f+m]),b=e.get(d[f+v]);this.options.groupOrderSwap(y,b,e),e.update(y),e.update(b);var _=u[f+m];u[f+m]=d[f+v],u[g]=_,f++}}}}}},{key:"_onGroupDragEnd",value:function(t){if(this.groupTouchParams.isDragging=!1,this.options.groupEditable.order&&this.groupTouchParams.group){t.stopPropagation();var e=this,i=e.groupTouchParams.group.groupId,n=e.groupsData.getDataSet(),r=wE.extend({},n.get(i));e.options.onMoveGroup(r,(function(t){if(t)t[n._idProp]=i,n.update(t);else{var r=n.getIds({order:e.options.groupOrder});if(!wE.equalArray(r,e.groupTouchParams.originalOrder))for(var o=e.groupTouchParams.originalOrder,s=Math.min(o.length,r.length),a=0;a=s)break;var l=av(r).call(r,o[a]),h=n.get(r[a]),u=n.get(o[a]);e.options.groupOrderSwap(h,u,n),n.update(h),n.update(u);var d=r[a];r[a]=o[a],r[l]=d,a++}}})),e.body.emitter.emit("groupDragged",{groupId:i}),this.toggleGroupDragClassName(this.groupTouchParams.group),this.groupTouchParams.group=null}}},{key:"_onSelectItem",value:function(t){if(this.options.selectable){var e=t.srcEvent&&(t.srcEvent.ctrlKey||t.srcEvent.metaKey),i=t.srcEvent&&t.srcEvent.shiftKey;if(e||i)this._onMultiSelectItem(t);else{var n=this.getSelection(),r=this.itemFromTarget(t),o=r&&r.selectable?[r.id]:[];this.setSelection(o);var s=this.getSelection();(s.length>0||n.length>0)&&this.body.emitter.emit("select",{items:s,event:t})}}}},{key:"_onMouseOver",value:function(t){var e=this.itemFromTarget(t);if(e&&e!==this.itemFromRelatedTarget(t)){var i=e.getTitle();if(this.options.showTooltips&&i){null==this.popup&&(this.popup=new IA(this.body.dom.root,this.options.tooltip.overflowMethod||"flip")),this.popup.setText(i);var n=this.body.dom.centerContainer,r=n.getBoundingClientRect();this.popup.setPosition(t.clientX-r.left+n.offsetLeft,t.clientY-r.top+n.offsetTop),this.setPopupTimer(this.popup)}else this.clearPopupTimer(),null!=this.popup&&this.popup.hide();this.body.emitter.emit("itemover",{item:e.id,event:t})}}},{key:"_onMouseOut",value:function(t){var e=this.itemFromTarget(t);e&&(e!==this.itemFromRelatedTarget(t)&&(this.clearPopupTimer(),null!=this.popup&&this.popup.hide(),this.body.emitter.emit("itemout",{item:e.id,event:t})))}},{key:"_onMouseMove",value:function(t){if(this.itemFromTarget(t)&&(null!=this.popupTimer&&this.setPopupTimer(this.popup),this.options.showTooltips&&this.options.tooltip.followMouse&&this.popup&&!this.popup.hidden)){var e=this.body.dom.centerContainer,i=e.getBoundingClientRect();this.popup.setPosition(t.clientX-i.left+e.offsetLeft,t.clientY-i.top+e.offsetTop),this.popup.show()}}},{key:"_onMouseWheel",value:function(t){this.touchParams.itemIsDragging&&this._onDragEnd(t)}},{key:"_onUpdateItem",value:function(t){if(this.options.selectable&&(this.options.editable.updateTime||this.options.editable.updateGroup)){var e=this;if(t){var i=e.itemsData.get(t.id);this.options.onUpdate(i,(function(t){t&&e.itemsData.update(t)}))}}}},{key:"_onDropObjectOnItem",value:function(t){var e=this.itemFromTarget(t),i=JSON.parse(t.dataTransfer.getData("text"));this.options.onDropObjectOnItem(i,e)}},{key:"_onAddItem",value:function(t){if(this.options.selectable&&this.options.editable.add){var e,i,n=this,r=this.options.snap||null,o=this.dom.frame.getBoundingClientRect(),s=this.options.rtl?o.right-t.center.x:t.center.x-o.left,a=this.body.util.toTime(s),l=this.body.util.getScale(),h=this.body.util.getStep();"drop"==t.type?((i=JSON.parse(t.dataTransfer.getData("text"))).content=i.content?i.content:"new item",i.start=i.start?i.start:r?r(a,l,h):a,i.type=i.type||"box",i[this.itemsData.idProp]=i.id||VM(),"range"!=i.type||i.end||(e=this.body.util.toTime(s+this.props.width/5),i.end=r?r(e,l,h):e)):((i={start:r?r(a,l,h):a,content:"new item"})[this.itemsData.idProp]=VM(),"range"===this.options.type&&(e=this.body.util.toTime(s+this.props.width/5),i.end=r?r(e,l,h):e));var u=this.groupFromTarget(t);u&&(i.group=u.groupId),i=this._cloneItemData(i),this.options.onAdd(i,(function(e){e&&(n.itemsData.add(e),"drop"==t.type&&n.setSelection([e.id]))}))}}},{key:"_onMultiSelectItem",value:function(t){var e=this;if(this.options.selectable){var n=this.itemFromTarget(t);if(n){var r=this.options.multiselect?this.getSelection():[];if((t.srcEvent&&t.srcEvent.shiftKey||!1||this.options.sequentialSelection)&&this.options.multiselect){var o=this.itemsData.get(n.id).group,s=void 0;this.options.multiselectPerGroup&&r.length>0&&(s=this.itemsData.get(r[0]).group),this.options.multiselectPerGroup&&null!=s&&s!=o||r.push(n.id);var a=i._getItemRange(this.itemsData.get(r));if(!this.options.multiselectPerGroup||s==o)for(var l in r=[],this.items)if(this.items.hasOwnProperty(l)){var h=this.items[l],u=h.data.start,d=void 0!==h.data.end?h.data.end:u;!(u>=a.min&&d<=a.max)||this.options.multiselectPerGroup&&s!=this.itemsData.get(h.id).group||h instanceof AA||r.push(h.id)}}else{var c=av(r).call(r,n.id);-1==c?r.push(n.id):_f(r).call(r,c,1)}var p=mm(r).call(r,(function(t){return e.getItemById(t).selectable}));this.setSelection(p),this.body.emitter.emit("select",{items:this.getSelection(),event:t})}}}},{key:"itemFromElement",value:function(t){for(var e=t;e;){if(e.hasOwnProperty("vis-item"))return e["vis-item"];e=e.parentNode}return null}},{key:"itemFromTarget",value:function(t){return this.itemFromElement(t.target)}},{key:"itemFromRelatedTarget",value:function(t){return this.itemFromElement(t.relatedTarget)}},{key:"groupFromTarget",value:function(t){var e=t.center?t.center.y:t.clientY,i=this.groupIds;i.length<=0&&this.groupsData&&(i=this.groupsData.getIds({order:this.options.groupOrder}));for(var n=0;n=a.top&&ea.top)return o}else if(0===n&&ee)&&(e=t.end):(null==e||t.start>e)&&(e=t.start)})),{min:i,max:e}}},{key:"itemSetFromTarget",value:function(t){for(var e=t.target;e;){if(e.hasOwnProperty("vis-itemset"))return e["vis-itemset"];e=e.parentNode}return null}}]),i}(IE);tI.types={background:AA,box:CA,range:EA,point:MA},tI.prototype._onAdd=tI.prototype._onUpdate;var eI,iI=!1,nI="background: #FFeeee; color: #dd0000",rI=function(){function t(){Ma(this,t)}return Yd(t,null,[{key:"validate",value:function(e,i,n){iI=!1,eI=i;var r=i;return void 0!==n&&(r=i[n]),t.parse(e,r,[]),iI}},{key:"parse",value:function(e,i,n){for(var r in e)e.hasOwnProperty(r)&&t.check(r,e,i,n)}},{key:"check",value:function(e,i,n,r){if(void 0!==n[e]||void 0!==n.__any__){var o=e,s=!0;void 0===n[e]&&void 0!==n.__any__&&(o="__any__",s="object"===t.getType(i[e]));var a=n[o];s&&void 0!==a.__type__&&(a=a.__type__),t.checkFields(e,i,n,o,a,r)}else t.getSuggestion(e,n,r)}},{key:"checkFields",value:function(e,i,n,r,o,s){var a=function(i){console.log("%c"+i+t.printLocation(s,e),nI)},l=t.getType(i[e]),h=o[l];void 0!==h?"array"===t.getType(h)&&-1===av(h).call(h,i[e])?(a('Invalid option detected in "'+e+'". Allowed values are:'+t.print(h)+' not "'+i[e]+'". '),iI=!0):"object"===l&&"__any__"!==r&&(s=wE.copyAndExtendArray(s,e),t.parse(i[e],n[r],s)):void 0===o.any&&(a('Invalid type received for "'+e+'". Expected: '+t.print(rp(o))+". Received ["+l+'] "'+i[e]+'"'),iI=!0)}},{key:"getType",value:function(t){var e=Nd(t);return"object"===e?null===t?"null":t instanceof Boolean?"boolean":t instanceof Number?"number":t instanceof String?"string":qc(t)?"array":t instanceof Date?"date":void 0!==t.nodeType?"dom":!0===t._isAMomentObject?"moment":"object":"number"===e?"number":"boolean"===e?"boolean":"string"===e?"string":void 0===e?"undefined":e}},{key:"getSuggestion",value:function(e,i,n){var r,o=t.findInOptions(e,i,n,!1),s=t.findInOptions(e,eI,[],!0);r=void 0!==o.indexMatch?" in "+t.printLocation(o.path,e,"")+'Perhaps it was incomplete? Did you mean: "'+o.indexMatch+'"?\n\n':s.distance<=4&&o.distance>s.distance?" in "+t.printLocation(o.path,e,"")+"Perhaps it was misplaced? Matching option found at: "+t.printLocation(s.path,s.closestMatch,""):o.distance<=8?'. Did you mean "'+o.closestMatch+'"?'+t.printLocation(o.path,e):". Did you mean one of these: "+t.print(rp(i))+t.printLocation(n,e),console.log('%cUnknown option detected: "'+e+'"'+r,nI),iI=!0}},{key:"findInOptions",value:function(e,i,n){var r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],o=1e9,s="",a=[],l=e.toLowerCase(),h=void 0;for(var u in i){var d=void 0;if(void 0!==i[u].__type__&&!0===r){var c=t.findInOptions(e,i[u],wE.copyAndExtendArray(n,u));o>c.distance&&(s=c.closestMatch,a=c.path,o=c.distance,h=c.indexMatch)}else{var p;-1!==av(p=u.toLowerCase()).call(p,l)&&(h=u),o>(d=t.levenshteinDistance(e,u))&&(s=u,a=wE.copyArray(n),o=d)}}return{closestMatch:s,path:a,distance:o,indexMatch:h}}},{key:"printLocation",value:function(t,e){for(var i="\n\n"+(arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Problem value found at: \n")+"options = {\n",n=0;n0&&void 0!==arguments[0]?arguments[0]:1;Ma(this,t),this.pixelRatio=e,this.generated=!1,this.centerCoordinates={x:144.5,y:144.5},this.r=289*.49,this.color={r:255,g:255,b:255,a:1},this.hueCircle=void 0,this.initialColor={r:255,g:255,b:255,a:1},this.previousColor=void 0,this.applied=!1,this.updateCallback=function(){},this.closeCallback=function(){},this._create()}return Yd(t,[{key:"insertTo",value:function(t){void 0!==this.hammer&&(this.hammer.destroy(),this.hammer=void 0),this.container=t,this.container.appendChild(this.frame),this._bindHammer(),this._setSize()}},{key:"setUpdateCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker update callback is not a function.");this.updateCallback=t}},{key:"setCloseCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker closing callback is not a function.");this.closeCallback=t}},{key:"_isColorString",value:function(t){if("string"==typeof t)return fI[t]}},{key:"setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if("none"!==t){var i,n=this._isColorString(t);if(void 0!==n&&(t=n),!0===wE.isString(t)){if(!0===wE.isValidRGB(t)){var r=t.substr(4).substr(0,t.length-5).split(",");i={r:r[0],g:r[1],b:r[2],a:1}}else if(!0===wE.isValidRGBA(t)){var o=t.substr(5).substr(0,t.length-6).split(",");i={r:o[0],g:o[1],b:o[2],a:o[3]}}else if(!0===wE.isValidHex(t)){var s=wE.hexToRGB(t);i={r:s.r,g:s.g,b:s.b,a:1}}}else if(t instanceof Object&&void 0!==t.r&&void 0!==t.g&&void 0!==t.b){var a=void 0!==t.a?t.a:"1.0";i={r:t.r,g:t.g,b:t.b,a:a}}if(void 0===i)throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: "+vv(t));this._setColor(i,e)}}},{key:"show",value:function(){void 0!==this.closeCallback&&(this.closeCallback(),this.closeCallback=void 0),this.applied=!1,this.frame.style.display="block",this._generateHueCircle()}},{key:"_hide",value:function(){var t=this;!0===(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&(this.previousColor=wE.extend({},this.color)),!0===this.applied&&this.updateCallback(this.initialColor),this.frame.style.display="none",Rv((function(){void 0!==t.closeCallback&&(t.closeCallback(),t.closeCallback=void 0)}),0)}},{key:"_save",value:function(){this.updateCallback(this.color),this.applied=!1,this._hide()}},{key:"_apply",value:function(){this.applied=!0,this.updateCallback(this.color),this._updatePicker(this.color)}},{key:"_loadLast",value:function(){void 0!==this.previousColor?this.setColor(this.previousColor,!1):alert("There is no last color to load...")}},{key:"_setColor",value:function(t){!0===(!(arguments.length>1&&void 0!==arguments[1])||arguments[1])&&(this.initialColor=wE.extend({},t)),this.color=t;var e=wE.RGBToHSV(t.r,t.g,t.b),i=2*Math.PI,n=this.r*e.s,r=this.centerCoordinates.x+n*Math.sin(i*e.h),o=this.centerCoordinates.y+n*Math.cos(i*e.h);this.colorPickerSelector.style.left=r-.5*this.colorPickerSelector.clientWidth+"px",this.colorPickerSelector.style.top=o-.5*this.colorPickerSelector.clientHeight+"px",this._updatePicker(t)}},{key:"_setOpacity",value:function(t){this.color.a=t/100,this._updatePicker(this.color)}},{key:"_setBrightness",value:function(t){var e=wE.RGBToHSV(this.color.r,this.color.g,this.color.b);e.v=t/100;var i=wE.HSVToRGB(e.h,e.s,e.v);i.a=this.color.a,this.color=i,this._updatePicker()}},{key:"_updatePicker",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.color,e=wE.RGBToHSV(t.r,t.g,t.b),i=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1)),i.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var n=this.colorPickerCanvas.clientWidth,r=this.colorPickerCanvas.clientHeight;i.clearRect(0,0,n,r),i.putImageData(this.hueCircle,0,0),i.fillStyle="rgba(0,0,0,"+(1-e.v)+")",i.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),Uv(i).call(i),this.brightnessRange.value=100*e.v,this.opacityRange.value=100*t.a,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}},{key:"_setSize",value:function(){this.colorPickerCanvas.style.width="100%",this.colorPickerCanvas.style.height="100%",this.colorPickerCanvas.width=289*this.pixelRatio,this.colorPickerCanvas.height=289*this.pixelRatio}},{key:"_create",value:function(){var t,e,i,n;if(this.frame=document.createElement("div"),this.frame.className="vis-color-picker",this.colorPickerDiv=document.createElement("div"),this.colorPickerSelector=document.createElement("div"),this.colorPickerSelector.className="vis-selector",this.colorPickerDiv.appendChild(this.colorPickerSelector),this.colorPickerCanvas=document.createElement("canvas"),this.colorPickerDiv.appendChild(this.colorPickerCanvas),this.colorPickerCanvas.getContext){var r=this.colorPickerCanvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(r.webkitBackingStorePixelRatio||r.mozBackingStorePixelRatio||r.msBackingStorePixelRatio||r.oBackingStorePixelRatio||r.backingStorePixelRatio||1),this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var o=document.createElement("DIV");o.style.color="red",o.style.fontWeight="bold",o.style.padding="10px",o.innerHTML="Error: your browser does not support HTML canvas",this.colorPickerCanvas.appendChild(o)}this.colorPickerDiv.className="vis-color",this.opacityDiv=document.createElement("div"),this.opacityDiv.className="vis-opacity",this.brightnessDiv=document.createElement("div"),this.brightnessDiv.className="vis-brightness",this.arrowDiv=document.createElement("div"),this.arrowDiv.className="vis-arrow",this.opacityRange=document.createElement("input");try{this.opacityRange.type="range",this.opacityRange.min="0",this.opacityRange.max="100"}catch(t){}this.opacityRange.value="100",this.opacityRange.className="vis-range",this.brightnessRange=document.createElement("input");try{this.brightnessRange.type="range",this.brightnessRange.min="0",this.brightnessRange.max="100"}catch(t){}this.brightnessRange.value="100",this.brightnessRange.className="vis-range",this.opacityDiv.appendChild(this.opacityRange),this.brightnessDiv.appendChild(this.brightnessRange);var s=this;this.opacityRange.onchange=function(){s._setOpacity(this.value)},this.opacityRange.oninput=function(){s._setOpacity(this.value)},this.brightnessRange.onchange=function(){s._setBrightness(this.value)},this.brightnessRange.oninput=function(){s._setBrightness(this.value)},this.brightnessLabel=document.createElement("div"),this.brightnessLabel.className="vis-label vis-brightness",this.brightnessLabel.innerHTML="brightness:",this.opacityLabel=document.createElement("div"),this.opacityLabel.className="vis-label vis-opacity",this.opacityLabel.innerHTML="opacity:",this.newColorDiv=document.createElement("div"),this.newColorDiv.className="vis-new-color",this.newColorDiv.innerHTML="new",this.initialColorDiv=document.createElement("div"),this.initialColorDiv.className="vis-initial-color",this.initialColorDiv.innerHTML="initial",this.cancelButton=document.createElement("div"),this.cancelButton.className="vis-button vis-cancel",this.cancelButton.innerHTML="cancel",this.cancelButton.onclick=Tp(t=this._hide).call(t,this,!1),this.applyButton=document.createElement("div"),this.applyButton.className="vis-button vis-apply",this.applyButton.innerHTML="apply",this.applyButton.onclick=Tp(e=this._apply).call(e,this),this.saveButton=document.createElement("div"),this.saveButton.className="vis-button vis-save",this.saveButton.innerHTML="save",this.saveButton.onclick=Tp(i=this._save).call(i,this),this.loadButton=document.createElement("div"),this.loadButton.className="vis-button vis-load",this.loadButton.innerHTML="load last",this.loadButton.onclick=Tp(n=this._loadLast).call(n,this),this.frame.appendChild(this.colorPickerDiv),this.frame.appendChild(this.arrowDiv),this.frame.appendChild(this.brightnessLabel),this.frame.appendChild(this.brightnessDiv),this.frame.appendChild(this.opacityLabel),this.frame.appendChild(this.opacityDiv),this.frame.appendChild(this.newColorDiv),this.frame.appendChild(this.initialColorDiv),this.frame.appendChild(this.cancelButton),this.frame.appendChild(this.applyButton),this.frame.appendChild(this.saveButton),this.frame.appendChild(this.loadButton)}},{key:"_bindHammer",value:function(){var t=this;this.drag={},this.pinch={},this.hammer=new uP(this.colorPickerCanvas),this.hammer.get("pinch").set({enable:!0}),dP(this.hammer,(function(e){t._moveSelector(e)})),this.hammer.on("tap",(function(e){t._moveSelector(e)})),this.hammer.on("panstart",(function(e){t._moveSelector(e)})),this.hammer.on("panmove",(function(e){t._moveSelector(e)})),this.hammer.on("panend",(function(e){t._moveSelector(e)}))}},{key:"_generateHueCircle",value:function(){if(!1===this.generated){var t=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var e,i,n,r,o=this.colorPickerCanvas.clientWidth,s=this.colorPickerCanvas.clientHeight;t.clearRect(0,0,o,s),this.centerCoordinates={x:.5*o,y:.5*s},this.r=.49*o;var a,l=2*Math.PI/360,h=1/this.r;for(n=0;n<360;n++)for(r=0;r3&&void 0!==arguments[3]?arguments[3]:1;Ma(this,t),this.parent=e,this.changedOptions=[],this.container=i,this.allowCreation=!1,this.options={},this.initialized=!1,this.popupCounter=0,this.defaultOptions={enabled:!1,filter:!0,container:void 0,showButton:!0},wE.extend(this.options,this.defaultOptions),this.configureOptions=n,this.moduleOptions={},this.domElements=[],this.popupDiv={},this.popupLimit=5,this.popupHistory={},this.colorPicker=new mI(r),this.wrapper=void 0}return Yd(t,[{key:"setOptions",value:function(t){if(void 0!==t){this.popupHistory={},this._removePopup();var e=!0;if("string"==typeof t)this.options.filter=t;else if(qc(t))this.options.filter=t.join();else if("object"===Nd(t)){if(null==t)throw new TypeError("options cannot be null");void 0!==t.container&&(this.options.container=t.container),void 0!==mm(t)&&(this.options.filter=mm(t)),void 0!==t.showButton&&(this.options.showButton=t.showButton),void 0!==t.enabled&&(e=t.enabled)}else"boolean"==typeof t?(this.options.filter=!0,e=t):"function"==typeof t&&(this.options.filter=t,e=!0);!1===mm(this.options)&&(e=!1),this.options.enabled=e}this._clean()}},{key:"setModuleOptions",value:function(t){this.moduleOptions=t,!0===this.options.enabled&&(this._clean(),void 0!==this.options.container&&(this.container=this.options.container),this._create())}},{key:"_create",value:function(){this._clean(),this.changedOptions=[];var t=mm(this.options),e=0,i=!1;for(var n in this.configureOptions)this.configureOptions.hasOwnProperty(n)&&(this.allowCreation=!1,i=!1,"function"==typeof t?i=(i=t(n,[]))||this._handleObject(this.configureOptions[n],[n],!0):!0!==t&&-1===av(t).call(t,n)||(i=!0),!1!==i&&(this.allowCreation=!0,e>0&&this._makeItem([]),this._makeHeader(n),this._handleObject(this.configureOptions[n],[n])),e++);this._makeButton(),this._push()}},{key:"_push",value:function(){this.wrapper=document.createElement("div"),this.wrapper.className="vis-configuration-wrapper",this.container.appendChild(this.wrapper);for(var t=0;t1?i-1:0),r=1;r2&&void 0!==arguments[2]&&arguments[2],n=document.createElement("div");return n.className="vis-configuration vis-config-label vis-config-s"+e.length,n.innerHTML=!0===i?wE.xss(""+t+":"):wE.xss(t+":"),n}},{key:"_makeDropdown",value:function(t,e,i){var n=document.createElement("select");n.className="vis-configuration vis-config-select";var r=0;void 0!==e&&-1!==av(t).call(t,e)&&(r=av(t).call(t,e));for(var o=0;oo&&1!==o&&(a.max=Math.ceil(e*u),h=a.max,l="range increased"),a.value=e}else a.value=n;var d=document.createElement("input");d.className="vis-configuration vis-config-rangeinput",d.value=Number(a.value);var c=this;a.onchange=function(){d.value=this.value,c._update(Number(this.value),i)},a.oninput=function(){d.value=this.value};var p=this._makeLabel(i[i.length-1],i),f=this._makeItem(i,p,a,d);""!==l&&this.popupHistory[f]!==h&&(this.popupHistory[f]=h,this._setupPopup(l,f))}},{key:"_makeButton",value:function(){var t=this;if(!0===this.options.showButton){var e=document.createElement("div");e.className="vis-configuration vis-config-button",e.innerHTML="generate options",e.onclick=function(){t._printOptions()},e.onmouseover=function(){e.className="vis-configuration vis-config-button hover"},e.onmouseout=function(){e.className="vis-configuration vis-config-button"},this.optionsContainer=document.createElement("div"),this.optionsContainer.className="vis-configuration vis-config-option-container",this.domElements.push(this.optionsContainer),this.domElements.push(e)}}},{key:"_setupPopup",value:function(t,e){var i=this;if(!0===this.initialized&&!0===this.allowCreation&&this.popupCounter1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=!1,r=mm(this.options),o=!1;for(var s in t)if(t.hasOwnProperty(s)){n=!0;var a=t[s],l=wE.copyAndExtendArray(e,s);if("function"==typeof r&&!1===(n=r(s,e))&&!qc(a)&&"string"!=typeof a&&"boolean"!=typeof a&&a instanceof Object&&(this.allowCreation=!1,n=this._handleObject(a,l,!0),this.allowCreation=!1===i),!1!==n){o=!0;var h=this._getValue(l);if(qc(a))this._handleArray(a,h,l);else if("string"==typeof a)this._makeTextInput(a,h,l);else if("boolean"==typeof a)this._makeCheckbox(a,h,l);else if(a instanceof Object){var u=!0;if(-1!==av(e).call(e,"physics")&&this.moduleOptions.physics.solver!==s&&(u=!1),!0===u)if(void 0!==a.enabled){var d=wE.copyAndExtendArray(l,"enabled"),c=this._getValue(d);if(!0===c){var p=this._makeLabel(s,l,!0);this._makeItem(l,p),o=this._handleObject(a,l)||o}else this._makeCheckbox(a,c,l)}else{var f=this._makeLabel(s,l,!0);this._makeItem(l,f),o=this._handleObject(a,l)||o}}else console.error("dont know how to handle",a,s,l)}}return o}},{key:"_handleArray",value:function(t,e,i){"string"==typeof t[0]&&"color"===t[0]?(this._makeColorField(t,e,i),t[1]!==e&&this.changedOptions.push({path:i,value:e})):"string"==typeof t[0]?(this._makeDropdown(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:e})):"number"==typeof t[0]&&(this._makeRange(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:Number(e)}))}},{key:"_update",value:function(t,e){var i=this._constructOptions(t,e);this.parent.body&&this.parent.body.emitter&&this.parent.body.emitter.emit&&this.parent.body.emitter.emit("configChange",i),this.initialized=!0,this.parent.setOptions(i)}},{key:"_constructOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=i;t="false"!==(t="true"===t||t)&&t;for(var r=0;rvar options = "+vv(t,null,2)+""}},{key:"getOptions",value:function(){for(var t={},e=0;eo)&&(o=i)})),null!==r&&null!==o){var s=this,a=this.itemSet.items[i[0]],l=-1*this._getScrollTop(),h=null,u=function(){var t=wI(s,a);t.shouldScroll&&t.itemTop!=h.itemTop&&(s._setScrollTop(-t.scrollOffset),s._redraw())},d=!e||void 0===e.zoom||e.zoom,c=(r+o)/2,p=d?1.1*(o-r):Math.max(this.range.end-this.range.start,1.1*(o-r)),f=!e||void 0===e.animation||e.animation;f||(h={shouldScroll:!1,scrollOffset:-1,itemTop:-1}),this.range.setRange(c-p/2,c+p/2,{animation:f},(function(){u(),Rv(u,100)}),(function(t,e,i){var n=wI(s,a);if(!1!==n&&(h||(h=n),h.itemTop!=n.itemTop||h.shouldScroll)){h.itemTop!=n.itemTop&&n.shouldScroll&&(h=n,l=-1*s._getScrollTop());var r=l,o=h.scrollOffset,u=i?o:r+(o-r)*t;s._setScrollTop(-u),e||s._redraw()}}))}}}},{key:"fit",value:function(t,e){var i,n=!t||void 0===t.animation||t.animation;1===this.itemsData.length&&void 0===this.itemsData.get()[0].end?(i=this.getDataRange(),this.moveTo(i.min.valueOf(),{animation:n},e)):(i=this.getItemRange(),this.range.setRange(i.min,i.max,{animation:n},e))}},{key:"getItemRange",value:function(){var t=this,e=this.getDataRange(),i=null!==e.min?e.min.valueOf():null,n=null!==e.max?e.max.valueOf():null,r=null,o=null;if(null!=i&&null!=n){var s=n-i;s<=0&&(s=10);var a=s/this.props.center.width,l={},h=0;if(Hp(wE).call(wE,this.itemSet.items,(function(t,e){if(t.groupShowing){l[e]=t.redraw(!0),h=l[e].length}})),h>0)for(var u=function(t){Hp(wE).call(wE,l,(function(e){e[t]()}))},d=0;dn&&(n=l,o=e)})),r&&o){var c=r.getWidthLeft()+10,p=o.getWidthRight()+10,f=this.props.center.width-c-p;f>0&&(this.options.rtl?(i=bI(r)-p*s/f,n=_I(o)+c*s/f):(i=bI(r)-c*s/f,n=_I(o)+p*s/f))}}return{min:null!=i?new Date(i):null,max:null!=n?new Date(n):null}}},{key:"getDataRange",value:function(){var t,e=null,i=null;this.itemsData&&Hp(t=this.itemsData).call(t,(function(t){var n=wE.convert(t.start,"Date").valueOf(),r=wE.convert(null!=t.end?t.end:t.start,"Date").valueOf();(null===e||ni)&&(i=r)}));return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}}},{key:"getEventProperties",value:function(t){var e=t.center?t.center.x:t.clientX,i=t.center?t.center.y:t.clientY,n=this.dom.centerContainer.getBoundingClientRect(),r=this.options.rtl?n.right-e:e-n.left,o=i-n.top,s=this.itemSet.itemFromTarget(t),a=this.itemSet.groupFromTarget(t),l=NP.customTimeFromTarget(t),h=this.itemSet.options.snap||null,u=this.body.util.getScale(),d=this.body.util.getStep(),c=this._toTime(r),p=h?h(c,u,d):c,f=wE.getTarget(t),m=null;return null!=s?m="item":null!=l?m="custom-time":wE.hasParent(f,this.timeAxis.dom.foreground)||this.timeAxis2&&wE.hasParent(f,this.timeAxis2.dom.foreground)?m="axis":wE.hasParent(f,this.itemSet.dom.labelSet)?m="group-label":wE.hasParent(f,this.currentTime.bar)?m="current-time":wE.hasParent(f,this.dom.center)&&(m="background"),{event:t,item:s?s.id:null,isCluster:!!s&&!!s.isCluster,items:s?s.items||[]:null,group:a?a.groupId:null,customTime:l?l.options.id:null,what:m,pageX:t.srcEvent?t.srcEvent.pageX:t.pageX,pageY:t.srcEvent?t.srcEvent.pageY:t.pageY,x:r,y:o,time:c,snappedTime:p}}},{key:"toggleRollingMode",value:function(){this.range.rolling?this.range.stopRolling():(null==this.options.rollingMode&&this.setOptions(this.options),this.range.startRolling())}},{key:"_redraw",value:function(){RP.prototype._redraw.call(this)}},{key:"_onFit",value:function(t){var e=t.start,i=t.end,n=t.animation;i?this.range.setRange(e,i,{animation:n}):this.moveTo(e.valueOf(),{animation:n})}}]),i}(RP);function bI(t){return wE.convert(t.data.start,"Date").valueOf()}function _I(t){var e=null!=t.data.end?t.data.end:t.data.start;return wE.convert(e,"Date").valueOf()}function wI(t,e){if(!e.parent)return!1;var i=t.options.rtl?t.props.rightContainer.height:t.props.leftContainer.height,n=t.props.center.height,r=e.parent,o=r.top,s=!0,a=t.timeAxis.options.orientation.axis,l=function(){return"bottom"==a?r.height-e.top-e.height:e.top},h=-1*t._getScrollTop(),u=o+l(),d=e.height;return uh+i?o+=l()+d-i+t.itemSet.options.margin.item.vertical:s=!1,{shouldScroll:s,scrollOffset:o=Math.min(o,n-i),itemTop:u}}var kI=function(){function t(e,i,n,r,o,s){var a=arguments.length>6&&void 0!==arguments[6]&&arguments[6],l=arguments.length>7&&void 0!==arguments[7]&&arguments[7];if(Ma(this,t),this.majorSteps=[1,2,5,10],this.minorSteps=[.25,.5,1,2],this.customLines=null,this.containerHeight=o,this.majorCharHeight=s,this._start=e,this._end=i,this.scale=1,this.minorStepIdx=-1,this.magnitudefactor=1,this.determineScale(),this.zeroAlign=a,this.autoScaleStart=n,this.autoScaleEnd=r,this.formattingFunction=l,n||r){var h=this,u=function(t){var e=t-t%(h.magnitudefactor*h.minorSteps[h.minorStepIdx]);return t%(h.magnitudefactor*h.minorSteps[h.minorStepIdx])>h.magnitudefactor*h.minorSteps[h.minorStepIdx]*.5?e+h.magnitudefactor*h.minorSteps[h.minorStepIdx]:e};n&&(this._start-=2*this.magnitudefactor*this.minorSteps[this.minorStepIdx],this._start=u(this._start)),r&&(this._end+=this.magnitudefactor*this.minorSteps[this.minorStepIdx],this._end=u(this._end)),this.determineScale()}}return Yd(t,[{key:"setCharHeight",value:function(t){this.majorCharHeight=t}},{key:"setHeight",value:function(t){this.containerHeight=t}},{key:"determineScale",value:function(){var t=this._end-this._start;this.scale=this.containerHeight/t;var e=this.majorCharHeight/this.scale,i=t>0?Math.round(Math.log(t)/Math.LN10):0;this.minorStepIdx=-1,this.magnitudefactor=Math.pow(10,i);var n=0;i<0&&(n=i);for(var r=!1,o=n;Math.abs(o)<=Math.abs(i);o++){this.magnitudefactor=Math.pow(10,o);for(var s=0;s=e){r=!0,this.minorStepIdx=s;break}}if(!0===r)break}}},{key:"is_major",value:function(t){return t%(this.magnitudefactor*this.majorSteps[this.minorStepIdx])==0}},{key:"getStep",value:function(){return this.magnitudefactor*this.minorSteps[this.minorStepIdx]}},{key:"getFirstMajor",value:function(){var t=this.magnitudefactor*this.majorSteps[this.minorStepIdx];return this.convertValue(this._start+(t-this._start%t)%t)}},{key:"formatValue",value:function(t){var e=t.toPrecision(5);return"function"==typeof this.formattingFunction&&(e=this.formattingFunction(t)),"number"==typeof e?"".concat(e):"string"==typeof e?e:t.toPrecision(5)}},{key:"getLines",value:function(){for(var t=[],e=this.getStep(),i=(e-this._start%e)%e,n=this._start+i;this._end-n>1e-5;n+=e)n!=this._start&&t.push({major:this.is_major(n),y:this.convertValue(n),val:this.formatValue(n)});return t}},{key:"followScale",value:function(t){var e=this.minorStepIdx,i=this._start,n=this._end,r=this,o=function(){r.magnitudefactor*=2},s=function(){r.magnitudefactor/=2};t.minorStepIdx<=1&&this.minorStepIdx<=1||t.minorStepIdx>1&&this.minorStepIdx>1||(t.minorStepIdxn+1e-5)s(),h=!1;else{if(!this.autoScaleStart&&this._start=0)){s(),h=!1;continue}console.warn("Can't adhere to given 'min' range, due to zeroalign")}this.autoScaleStart&&this.autoScaleEnd&&d=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,o=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw o}}}}function DI(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i=0&&t._redrawLabel(n-2,e.val,i,"vis-y-axis vis-major",t.props.majorCharHeight),!0===t.master&&(r?t._redrawLine(n,i,"vis-grid vis-horizontal vis-major",t.options.majorLinesOffset,t.props.majorLineWidth):t._redrawLine(n,i,"vis-grid vis-horizontal vis-minor",t.options.minorLinesOffset,t.props.minorLineWidth))}));var a=0;void 0!==this.options[i].title&&void 0!==this.options[i].title.text&&(a=this.props.titleCharHeight);var l=!0===this.options.icons?Math.max(this.options.iconWidth,a)+this.options.labelOffsetX+15:a+this.options.labelOffsetX+15;return this.maxLabelSize>this.width-l&&!0===this.options.visible?(this.width=this.maxLabelSize+l,this.options.width="".concat(this.width,"px"),Ub(this.DOMelements.lines),Ub(this.DOMelements.labels),this.redraw(),e=!0):this.maxLabelSizethis.minWidth?(this.width=Math.max(this.minWidth,this.maxLabelSize+l),this.options.width="".concat(this.width,"px"),Ub(this.DOMelements.lines),Ub(this.DOMelements.labels),this.redraw(),e=!0):(Ub(this.DOMelements.lines),Ub(this.DOMelements.labels),e=!1),e}},{key:"convertValue",value:function(t){return this.scale.convertValue(t)}},{key:"screenToValue",value:function(t){return this.scale.screenToValue(t)}},{key:"_redrawLabel",value:function(t,e,i,n,r){var o=$b("div",this.DOMelements.labels,this.dom.frame);o.className=n,o.innerHTML=wE.xss(e),"left"===i?(o.style.left="-".concat(this.options.labelOffsetX,"px"),o.style.textAlign="right"):(o.style.right="-".concat(this.options.labelOffsetX,"px"),o.style.textAlign="left"),o.style.top="".concat(t-.5*r+this.options.labelOffsetY,"px"),e+="";var s=Math.max(this.props.majorCharWidth,this.props.minorCharWidth);this.maxLabelSize0&&(i=Math.min(i,Math.abs(e[n-1].screen_x-e[n].screen_x))),0===i&&(void 0===t[e[n].screen_x]&&(t[e[n].screen_x]={amount:0,resolved:0,accumulatedPositive:0,accumulatedNegative:0}),t[e[n].screen_x].amount+=1)},OI._getSafeDrawData=function(t,e,i){var n,r;return t0?(n=t0){_T(t).call(t,(function(t,e){return t.screen_x===e.screen_x?t.groupIde[o].screen_y?e[o].screen_y:n,r=rt[s].accumulatedNegative?t[s].accumulatedNegative:n)>t[s].accumulatedPositive?t[s].accumulatedPositive:n,r=(r=r0){return 1==e.options.interpolation.enabled?EI._catmullRom(t,e):EI._linear(t)}},EI.drawIcon=function(t,e,i,n,r,o){var s,a,l=.5*r,h=qb("rect",o.svgElements,o.svg);(h.setAttributeNS(null,"x",e),h.setAttributeNS(null,"y",i-l),h.setAttributeNS(null,"width",n),h.setAttributeNS(null,"height",2*l),h.setAttributeNS(null,"class","vis-outline"),(s=qb("path",o.svgElements,o.svg)).setAttributeNS(null,"class",t.className),void 0!==t.style&&s.setAttributeNS(null,"style",t.style),s.setAttributeNS(null,"d","M"+e+","+i+" L"+(e+n)+","+i),1==t.options.shaded.enabled&&(a=qb("path",o.svgElements,o.svg),"top"==t.options.shaded.orientation?a.setAttributeNS(null,"d","M"+e+", "+(i-l)+"L"+e+","+i+" L"+(e+n)+","+i+" L"+(e+n)+","+(i-l)):a.setAttributeNS(null,"d","M"+e+","+i+" L"+e+","+(i+l)+" L"+(e+n)+","+(i+l)+"L"+(e+n)+","+i),a.setAttributeNS(null,"class",t.className+" vis-icon-fill"),void 0!==t.options.shaded.style&&""!==t.options.shaded.style&&a.setAttributeNS(null,"style",t.options.shaded.style)),1==t.options.drawPoints.enabled)&&Zb(e+.5*n,i,{style:t.options.drawPoints.style,styles:t.options.drawPoints.styles,size:t.options.drawPoints.size,className:t.className},o.svgElements,o.svg)},EI.drawShading=function(t,e,i,n){if(1==e.options.shaded.enabled){var r,o=Number(n.svg.style.height.replace("px","")),s=qb("path",n.svgElements,n.svg),a="L";1==e.options.interpolation.enabled&&(a="C");var l=0;l="top"==e.options.shaded.orientation?0:"bottom"==e.options.shaded.orientation?o:Math.min(Math.max(0,e.zeroPosition),o),r="group"==e.options.shaded.orientation&&null!=i&&null!=i?"M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,a,!1)+" L"+i[i.length-1][0]+","+i[i.length-1][1]+" "+this.serializePath(i,a,!0)+i[0][0]+","+i[0][1]+" Z":"M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,a,!1)+" V"+l+" H"+t[0][0]+" Z",s.setAttributeNS(null,"class",e.className+" vis-fill"),void 0!==e.options.shaded.style&&s.setAttributeNS(null,"style",e.options.shaded.style),s.setAttributeNS(null,"d",r)}},EI.draw=function(t,e,i){if(null!=t&&null!=t){var n=qb("path",i.svgElements,i.svg);n.setAttributeNS(null,"class",e.className),void 0!==e.style&&n.setAttributeNS(null,"style",e.style);var r="L";1==e.options.interpolation.enabled&&(r="C"),n.setAttributeNS(null,"d","M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,r,!1))}},EI.serializePath=function(t,e,i){if(t.length<2)return"";var n,r=e;if(i)for(n=t.length-2;n>0;n--)r+=t[n][0]+","+t[n][1]+" ";else for(n=1;n0&&(f=1/f),(m=3*v*(v+g))>0&&(m=1/m),a={screen_x:(-b*n.screen_x+c*r.screen_x+_*o.screen_x)*f,screen_y:(-b*n.screen_y+c*r.screen_y+_*o.screen_y)*f},l={screen_x:(y*r.screen_x+p*o.screen_x-b*s.screen_x)*m,screen_y:(y*r.screen_y+p*o.screen_y-b*s.screen_y)*m},0==a.screen_x&&0==a.screen_y&&(a=r),0==l.screen_x&&0==l.screen_y&&(l=o),k.push([a.screen_x,a.screen_y]),k.push([l.screen_x,l.screen_y]),k.push([o.screen_x,o.screen_y]);return k},EI._linear=function(t){for(var e=[],i=0;ie.x?1:-1}))):this.itemsData=[]},PI.prototype.getItems=function(){return this.itemsData},PI.prototype.setZeroPosition=function(t){this.zeroPosition=t},PI.prototype.setOptions=function(t){if(void 0!==t){wE.selectiveDeepExtend(["sampling","style","sort","yAxisOrientation","barChart","zIndex","excludeFromStacking","excludeFromLegend"],this.options,t),"function"==typeof t.drawPoints&&(t.drawPoints={onRender:t.drawPoints}),wE.mergeOptions(this.options,t,"interpolation"),wE.mergeOptions(this.options,t,"drawPoints"),wE.mergeOptions(this.options,t,"shaded"),t.interpolation&&"object"==Nd(t.interpolation)&&t.interpolation.parametrization&&("uniform"==t.interpolation.parametrization?this.options.interpolation.alpha=0:"chordal"==t.interpolation.parametrization?this.options.interpolation.alpha=1:(this.options.interpolation.parametrization="centripetal",this.options.interpolation.alpha=.5))}},PI.prototype.update=function(t){this.group=t,this.content=t.content||"graph",this.className=t.className||this.className||"vis-graph-group"+this.groupsUsingDefaultStyles[0]%10,this.visible=void 0===t.visible||t.visible,this.style=t.style,this.setOptions(t.options)},PI.prototype.getLegend=function(t,e,i,n,r){null!=i&&null!=i||(i={svg:document.createElementNS("http://www.w3.org/2000/svg","svg"),svgElements:{},options:this.options,groups:[this]});switch(null!=n&&null!=n||(n=0),null!=r&&null!=r||(r=.5*e),this.options.style){case"line":EI.drawIcon(this,n,r,t,e,i);break;case"points":case"point":TI.drawIcon(this,n,r,t,e,i);break;case"bar":OI.drawIcon(this,n,r,t,e,i)}return{icon:i.svg,label:this.content,orientation:this.options.yAxisOrientation}},PI.prototype.getYRange=function(t){for(var e=t[0].y,i=t[0].y,n=0;nt[n].y?t[n].y:e,i=i");this.dom.textArea.innerHTML=wE.xss(o),this.dom.textArea.style.lineHeight=.75*this.options.iconSize+this.options.iconSpacing+"px"}},AI.prototype.drawLegendIcons=function(){if(this.dom.frame.parentNode){var t=rp(this.groups);_T(t).call(t,(function(t,e){return t0){var s={};for(this._getRelevantData(o,s,n,r),this._applySampling(o,s),e=0;e0)switch(t.options.style){case"line":l.hasOwnProperty(o[e])||(l[o[e]]=EI.calcPath(s[o[e]],t)),EI.draw(l[o[e]],t,this.framework);case"point":case"points":"point"!=t.options.style&&"points"!=t.options.style&&1!=t.options.drawPoints.enabled||TI.draw(s[o[e]],t,this.framework)}}}return Ub(this.svgElements),!1},LI.prototype._stack=function(t,e){var i,n,r,o,s;i=0;for(var a=0;at[a].x){s=e[l],o=0==l?s:e[l-1],i=l;break}}void 0===s&&(o=e[e.length-1],s=e[e.length-1]),n=s.x-o.x,r=s.y-o.y,t[a].y=0==n?t[a].orginalY+s.y:t[a].orginalY+r/n*(t[a].x-o.x)+o.y}},LI.prototype._getRelevantData=function(t,e,i,n){var r,o,s,a;if(t.length>0)for(o=0;o0)for(var i=0;i0){var r,o=n.length,s=o/(this.body.util.toGlobalScreen(n[n.length-1].x)-this.body.util.toGlobalScreen(n[0].x));r=Math.min(Math.ceil(.2*o),Math.max(1,Math.round(s)));for(var a=new Array(o),l=0;l0){for(o=0;o0&&(r=this.groups[t[o]],!0===s.stack&&"bar"===s.style?"left"===s.yAxisOrientation?a=Yc(a).call(a,n):l=Yc(l).call(l,n):i[t[o]]=r.getYRange(n,t[o]));OI.getStackedYRange(a,i,t,"__barStackLeft","left"),OI.getStackedYRange(l,i,t,"__barStackRight","right")}},LI.prototype._updateYAxis=function(t,e){var i,n,r=!1,o=!1,s=!1,a=1e9,l=1e9,h=-1e9,u=-1e9;if(t.length>0){for(var d=0;di?i:a,h=hi?i:l,u=uo?o:t,e=null==e||e0&&h.push(u.screenToValue(r)),!d.hidden&&this.itemsData.length>0&&h.push(d.screenToValue(r)),{event:t,customTime:s?s.options.id:null,what:l,pageX:t.srcEvent?t.srcEvent.pageX:t.pageX,pageY:t.srcEvent?t.srcEvent.pageY:t.pageY,x:n,y:r,time:o,value:h}},GI.prototype._createConfigurator=function(){return new vI(this,this.dom.container,BI)};var WI=Jb();sO.locale(WI);var VI={Core:RP,DateUtil:nP,Range:oP,stack:gA,TimeStep:cP,components:{items:{Item:DA,BackgroundItem:AA,BoxItem:CA,ClusterItem:WA,PointItem:MA,RangeItem:EA},BackgroundGroup:wA,Component:IE,CurrentTime:jP,CustomTime:NP,DataAxis:CI,DataScale:kI,GraphGroup:PI,Group:bA,ItemSet:tI,Legend:AI,LineGraph:LI,TimeAxis:mP}};t.DOMutil=Qb,t.DataSet=nO,t.DataView=rO,t.Graph2d=GI,t.Hammer=uP,t.Queue=tO,t.Timeline=yI,t.keycharm=gP,t.moment=sO,t.timeline=VI,t.util=Wb})); +//# sourceMappingURL=vis-timeline-graph2d.min.js.map From 959cc95048354dc47668d05268b388397e282fa1 Mon Sep 17 00:00:00 2001 From: Wenchen Fan Date: Sat, 28 Feb 2026 23:01:42 +0800 Subject: [PATCH 096/130] [SPARK-55702][SQL][FOLLOWUP] Clean up dead error code and fix flaky window filter test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? Follow-up to #54501. Two cleanups: 1. **Remove dead error code**: The `windowAggregateFunctionWithFilterNotSupportedError` method in `QueryCompilationErrors.scala` and its `_LEGACY_ERROR_TEMP_1030` error class in `error-conditions.json` were left behind after #54501 removed their only call site. 2. **Fix flaky `first_value`/`last_value` test**: The window filter test used `ORDER BY val_long` with a ROWS frame, but `val_long` has duplicate values in the test data (e.g., three rows with `val_long=1`), making `first_value`/`last_value` results non-deterministic. Added `val` and `cate` as tiebreaker columns and used `NULLS LAST` so the output is both stable and meaningful (without NULLS LAST, the first matching 'a' row has `val=NULL`, making `first_a` always NULL). ### Why are the changes needed? 1. Dead code should be cleaned up. 2. Non-deterministic tests can cause spurious failures. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Re-ran `SQLQueryTestSuite` for `window.sql` — all 4 tests pass across all config dimensions. ### Was this patch authored or co-authored using generative AI tooling? Yes. cursor Closes #54557 from cloud-fan/follow. Authored-by: Wenchen Fan Signed-off-by: Kent Yao --- .../src/main/resources/error/error-conditions.json | 5 ----- .../spark/sql/errors/QueryCompilationErrors.scala | 6 ------ .../sql-tests/analyzer-results/window.sql.out | 10 +++++----- .../src/test/resources/sql-tests/inputs/window.sql | 6 +++--- .../test/resources/sql-tests/results/window.sql.out | 12 ++++++------ 5 files changed, 14 insertions(+), 25 deletions(-) diff --git a/common/utils/src/main/resources/error/error-conditions.json b/common/utils/src/main/resources/error/error-conditions.json index b76e3b5c8d56e..6c2a648ec52e2 100644 --- a/common/utils/src/main/resources/error/error-conditions.json +++ b/common/utils/src/main/resources/error/error-conditions.json @@ -8008,11 +8008,6 @@ "count(.*) is not allowed. Please use count(*) or expand the columns manually, e.g. count(col1, col2)." ] }, - "_LEGACY_ERROR_TEMP_1030" : { - "message" : [ - "Window aggregate function with filter predicate is not supported yet." - ] - }, "_LEGACY_ERROR_TEMP_1031" : { "message" : [ "It is not allowed to use a window function inside an aggregate function. Please use the inner window function in a sub-query." diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala index 8cdd734def4aa..edf2dfe545c7a 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala @@ -836,12 +836,6 @@ private[sql] object QueryCompilationErrors extends QueryErrorsBase with Compilat messageParameters = Map("expression" -> expression)) } - def windowAggregateFunctionWithFilterNotSupportedError(): Throwable = { - new AnalysisException( - errorClass = "_LEGACY_ERROR_TEMP_1030", - messageParameters = Map.empty) - } - def windowFunctionInsideAggregateFunctionNotAllowedError(): Throwable = { new AnalysisException( errorClass = "_LEGACY_ERROR_TEMP_1031", diff --git a/sql/core/src/test/resources/sql-tests/analyzer-results/window.sql.out b/sql/core/src/test/resources/sql-tests/analyzer-results/window.sql.out index 76c0fb1919ce1..11240c52e9c86 100644 --- a/sql/core/src/test/resources/sql-tests/analyzer-results/window.sql.out +++ b/sql/core/src/test/resources/sql-tests/analyzer-results/window.sql.out @@ -688,17 +688,17 @@ Project [cate#x, sum(val) OVER (PARTITION BY cate ORDER BY val ASC NULLS FIRST R -- !query SELECT val, cate, -first_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long +first_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long NULLS LAST, val NULLS LAST, cate NULLS LAST ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS first_a, -last_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long +last_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long NULLS LAST, val NULLS LAST, cate NULLS LAST ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS last_a -FROM testData ORDER BY val_long, cate +FROM testData ORDER BY val_long NULLS LAST, val NULLS LAST, cate NULLS LAST -- !query analysis Project [val#x, cate#x, first_a#x, last_a#x] -+- Sort [val_long#xL ASC NULLS FIRST, cate#x ASC NULLS FIRST], true ++- Sort [val_long#xL ASC NULLS LAST, val#x ASC NULLS LAST, cate#x ASC NULLS LAST], true +- Project [val#x, cate#x, first_a#x, last_a#x, val_long#xL] +- Project [val#x, cate#x, _w0#x, val_long#xL, first_a#x, last_a#x, first_a#x, last_a#x] - +- Window [first_value(val#x, false) FILTER (WHERE _w0#x) windowspecdefinition(val_long#xL ASC NULLS FIRST, specifiedwindowframe(RowFrame, unboundedpreceding$(), currentrow$())) AS first_a#x, last_value(val#x, false) FILTER (WHERE _w0#x) windowspecdefinition(val_long#xL ASC NULLS FIRST, specifiedwindowframe(RowFrame, unboundedpreceding$(), currentrow$())) AS last_a#x], [val_long#xL ASC NULLS FIRST] + +- Window [first_value(val#x, false) FILTER (WHERE _w0#x) windowspecdefinition(val_long#xL ASC NULLS LAST, val#x ASC NULLS LAST, cate#x ASC NULLS LAST, specifiedwindowframe(RowFrame, unboundedpreceding$(), currentrow$())) AS first_a#x, last_value(val#x, false) FILTER (WHERE _w0#x) windowspecdefinition(val_long#xL ASC NULLS LAST, val#x ASC NULLS LAST, cate#x ASC NULLS LAST, specifiedwindowframe(RowFrame, unboundedpreceding$(), currentrow$())) AS last_a#x], [val_long#xL ASC NULLS LAST, val#x ASC NULLS LAST, cate#x ASC NULLS LAST] +- Project [val#x, cate#x, (cate#x = a) AS _w0#x, val_long#xL] +- SubqueryAlias testdata +- View (`testData`, [val#x, val_long#xL, val_double#x, val_date#x, val_timestamp#x, cate#x]) diff --git a/sql/core/src/test/resources/sql-tests/inputs/window.sql b/sql/core/src/test/resources/sql-tests/inputs/window.sql index 586fe88ac3051..3a453e1c80e7e 100644 --- a/sql/core/src/test/resources/sql-tests/inputs/window.sql +++ b/sql/core/src/test/resources/sql-tests/inputs/window.sql @@ -184,11 +184,11 @@ WINDOW w AS (PARTITION BY cate ORDER BY val); -- window aggregate with filter predicate: first_value/last_value (imperative aggregate) SELECT val, cate, -first_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long +first_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long NULLS LAST, val NULLS LAST, cate NULLS LAST ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS first_a, -last_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long +last_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long NULLS LAST, val NULLS LAST, cate NULLS LAST ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS last_a -FROM testData ORDER BY val_long, cate; +FROM testData ORDER BY val_long NULLS LAST, val NULLS LAST, cate NULLS LAST; -- window aggregate with filter predicate: multiple aggregates with different filters SELECT val, cate, diff --git a/sql/core/src/test/resources/sql-tests/results/window.sql.out b/sql/core/src/test/resources/sql-tests/results/window.sql.out index 44c3b175868de..3ee7673df6410 100644 --- a/sql/core/src/test/resources/sql-tests/results/window.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/window.sql.out @@ -669,23 +669,23 @@ b 6 -- !query SELECT val, cate, -first_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long +first_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long NULLS LAST, val NULLS LAST, cate NULLS LAST ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS first_a, -last_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long +last_value(val) FILTER (WHERE cate = 'a') OVER(ORDER BY val_long NULLS LAST, val NULLS LAST, cate NULLS LAST ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS last_a -FROM testData ORDER BY val_long, cate +FROM testData ORDER BY val_long NULLS LAST, val NULLS LAST, cate NULLS LAST -- !query schema struct -- !query output -NULL NULL 1 NULL -1 b 1 NULL +1 a 1 1 3 NULL 1 1 NULL a 1 NULL 1 a 1 1 -1 a 1 1 2 b 1 1 2 a 1 2 3 b 1 2 +1 b 1 2 +NULL NULL 1 2 -- !query From 730d375c22e3226fda3bd9c7501762a2007f522d Mon Sep 17 00:00:00 2001 From: Wenchen Fan Date: Sat, 28 Feb 2026 23:08:01 +0800 Subject: [PATCH 097/130] [SPARK-55756][SQL][TESTS] Add --DEBUG directive for golden file test framework ### What changes were proposed in this pull request? Add a `--DEBUG` marker directive for the SQL golden file test framework (`SQLQueryTestSuite`). When placed on its own line before a query in an input `.sql` file, it enables a focused debug mode: - **Selective execution**: Only `--DEBUG`-marked queries and setup commands (CREATE TABLE, INSERT, SET, etc.) are executed; all other queries are skipped. - **Full error details**: Failed queries print the complete stacktrace to the console. - **Golden comparison**: Results are still compared against the golden file so you can verify correctness. - **Safety net**: The test always fails at the end with a reminder to remove `--DEBUG` markers before committing. - **DataFrame access**: Documentation guides users to set a breakpoint in `runDebugQueries` to inspect the `DataFrame` instance for ad-hoc plan analysis. Example usage in an input file: ```sql CREATE TABLE t (id INT, val INT) USING parquet; INSERT INTO t VALUES (1, 10), (2, 20); -- this query is skipped in debug mode SELECT count(*) FROM t; -- this is the query I'm debugging --DEBUG SELECT sum(val) OVER (ORDER BY id) FROM t; ``` Example console output when running the test: ``` === DEBUG: Query #3 === SQL: SELECT sum(val) OVER (ORDER BY id) FROM t Golden answer: matches ``` When the debug query fails: ``` === DEBUG: Query #3 === SQL: SELECT sum(val) OVER (ORDER BY id) FROM t org.apache.spark.sql.AnalysisException: [ERROR_CLASS] ... at org.apache.spark.sql.catalyst.analysis... at ... Golden answer: matches ``` ### Why are the changes needed? Debugging golden file test failures is currently painful: 1. You must run all queries even if only one needs debugging. 2. Error output is minimal (just the error class/message), with no stacktrace. 3. There is no way to access the `DataFrame` instance for plan inspection. This change addresses all three issues with a simple, zero-config marker that can be temporarily added during development. ### Does this PR introduce _any_ user-facing change? No. This is a test infrastructure improvement only. ### How was this patch tested? - Manually tested with `--DEBUG` markers on both passing and failing queries in `inline-table.sql`. - Verified backward compatibility: tests pass normally when no `--DEBUG` markers are present. - Verified debug mode output includes full stacktraces, golden answer comparison, and the safety-fail message. ### Was this patch authored or co-authored using generative AI tooling? Yes. cursor Closes #54554 from cloud-fan/golden. Authored-by: Wenchen Fan Signed-off-by: Kent Yao --- .../apache/spark/sql/SQLQueryTestHelper.scala | 27 ++- .../apache/spark/sql/SQLQueryTestSuite.scala | 166 ++++++++++++++++-- 2 files changed, 176 insertions(+), 17 deletions(-) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/SQLQueryTestHelper.scala b/sql/core/src/test/scala/org/apache/spark/sql/SQLQueryTestHelper.scala index 899fd85a8bb80..5ad9605c7d78b 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/SQLQueryTestHelper.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/SQLQueryTestHelper.scala @@ -400,11 +400,16 @@ trait SQLQueryTestHelper extends SQLConfHelper with Logging { protected def splitCommentsAndCodes(input: String): (Array[String], Array[String]) = input.split("\n").partition { line => val newLine = line.trim - newLine.startsWith("--") && !newLine.startsWith("--QUERY-DELIMITER") + newLine.startsWith("--") && !newLine.startsWith("--QUERY-DELIMITER") && + newLine != "--DEBUG" } - protected def getQueries(code: Array[String], comments: Array[String], - allTestCases: Seq[TestCase]): Seq[String] = { + /** + * Parses queries from code lines and returns each query paired with a Boolean indicating + * whether it was preceded by a --DEBUG marker. + */ + protected def getQueriesWithDebugFlag(code: Array[String], comments: Array[String], + allTestCases: Seq[TestCase]): Seq[(String, Boolean)] = { def splitWithSemicolon(seq: Seq[String]) = { seq.mkString("\n").split("(?<=[^\\\\]);") } @@ -450,10 +455,18 @@ trait SQLQueryTestHelper extends SQLConfHelper with Logging { splitWithSemicolon(allCode.toImmutableArraySeq).toSeq } - // List of SQL queries to run - tempQueries.map(_.trim).filter(_ != "") - // Fix misplacement when comment is at the end of the query. - .map(_.split("\n").filterNot(_.startsWith("--")).mkString("\n")).map(_.trim).filter(_ != "") + // Detect --DEBUG markers before stripping comment lines from each query. + tempQueries.map(_.trim).filter(_ != "").map { query => + val lines = query.split("\n") + val isDebug = lines.exists(_.trim == "--DEBUG") + val cleanedQuery = lines.filterNot(_.startsWith("--")).mkString("\n").trim + (cleanedQuery, isDebug) + }.filter(_._1 != "") + } + + protected def getQueries(code: Array[String], comments: Array[String], + allTestCases: Seq[TestCase]): Seq[String] = { + getQueriesWithDebugFlag(code, comments, allTestCases).map(_._1) } protected def getSparkSettings(comments: Array[String]): Array[(String, String)] = { diff --git a/sql/core/src/test/scala/org/apache/spark/sql/SQLQueryTestSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/SQLQueryTestSuite.scala index a57c72f5fc155..f4be4c38ce932 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/SQLQueryTestSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/SQLQueryTestSuite.scala @@ -17,7 +17,7 @@ package org.apache.spark.sql -import java.io.File +import java.io.{File, PrintWriter, StringWriter} import java.net.URI import java.nio.file.Files import java.util.Locale @@ -84,6 +84,16 @@ import org.apache.spark.util.Utils * times, each time picks one config set from each dimension, until all the combinations are * tried. For example, if dimension 1 has 2 lines, dimension 2 has 3 lines, this testing file * will be run 6 times (cartesian product). + * 6. A line with --DEBUG (on its own line before a query) marks that query for debug mode. + * When any --DEBUG marker is present, the test enters debug mode: + * - Commands (CREATE TABLE, INSERT, DROP, SET, etc.) are always executed automatically. + * - Only --DEBUG-marked non-command queries are executed; all others are skipped. + * - For failed queries, the full error stacktrace is printed to the console. + * - Query results are still compared against the golden file. + * - The test always fails at the end with a reminder to remove --DEBUG markers. + * To inspect the DataFrame interactively, set a breakpoint in `runDebugQueries` at the + * line where `localSparkSession.sql(sql)` is called, then evaluate the DataFrame in the + * debugger (e.g., `df.queryExecution.analyzed`, `df.explain(true)`). * * For example: * {{{ @@ -92,6 +102,17 @@ import org.apache.spark.util.Utils * select current_date; * }}} * + * To debug a specific query, add --DEBUG before it: + * {{{ + * CREATE TABLE t (id INT, val INT) USING parquet; + * INSERT INTO t VALUES (1, 10), (2, 20); + * -- this query is skipped in debug mode + * SELECT count(*) FROM t; + * -- this is the query I'm debugging + * --DEBUG + * SELECT sum(val) OVER (ORDER BY id) FROM t; + * }}} + * * The format for golden result files look roughly like: * {{{ * -- some header information @@ -232,15 +253,18 @@ class SQLQueryTestSuite extends QueryTest with SharedSparkSession with SQLHelper protected def runSqlTestCase(testCase: TestCase, listTestCases: Seq[TestCase]): Unit = { val input = Files.readString(new File(testCase.inputFile).toPath) val (comments, code) = splitCommentsAndCodes(input) - val queries = getQueries(code, comments, listTestCases) + val queriesWithDebug = getQueriesWithDebugFlag(code, comments, listTestCases) val settings = getSparkSettings(comments) + val debugMode = queriesWithDebug.exists(_._2) && !testCase.isInstanceOf[AnalyzerTest] - if (regenerateGoldenFiles) { - runQueries(queries, testCase, settings.toImmutableArraySeq) + if (debugMode && !regenerateGoldenFiles) { + runDebugQueries(queriesWithDebug, testCase, settings.toImmutableArraySeq) + } else if (regenerateGoldenFiles) { + runQueries(queriesWithDebug.map(_._1), testCase, settings.toImmutableArraySeq) } else { val configSets = getSparkConfigDimensions(comments) runQueriesWithSparkConfigDimensions( - queries, testCase, settings, configSets) + queriesWithDebug.map(_._1), testCase, settings, configSets) } } @@ -287,12 +311,13 @@ class SQLQueryTestSuite extends QueryTest with SharedSparkSession with SQLHelper } } - protected def runQueries( - queries: Seq[String], + /** + * Creates and configures a local SparkSession for running test queries. + * Handles UDF/UDTF registration, SQL config, and TPCDS table setup. + */ + private def setupLocalSession( testCase: TestCase, - sparkConfigSet: Seq[(String, String)]): Unit = { - // Create a local SparkSession to have stronger isolation between different test cases. - // This does not isolate catalog changes. + sparkConfigSet: Seq[(String, String)]): SparkSession = { val localSparkSession = spark.newSession() testCase match { @@ -337,6 +362,127 @@ class SQLQueryTestSuite extends QueryTest with SharedSparkSession with SQLHelper } } + localSparkSession + } + + /** + * Runs queries in debug mode. Only commands and --DEBUG-marked queries are executed. + * Failed debug queries print the full error stacktrace. Results are compared against + * the golden file. The test always fails at the end to prevent accidental commits. + * + * To inspect the DataFrame interactively, set a breakpoint at the line where + * `localSparkSession.sql(sql)` is called inside this method, then evaluate the DataFrame + * in the debugger (e.g., `df.queryExecution.analyzed`, `df.explain(true)`). + */ + protected def runDebugQueries( + queriesWithDebug: Seq[(String, Boolean)], + testCase: TestCase, + sparkConfigSet: Seq[(String, String)]): Unit = { + val localSparkSession = setupLocalSession(testCase, sparkConfigSet) + val lowercaseTestCase = testCase.name.toLowerCase(Locale.ROOT) + val segmentsPerQuery = 3 + + val goldenFileExists = new File(testCase.resultFile).exists() + val segments = if (goldenFileExists) { + Files.readString(new File(testCase.resultFile).toPath).split("-- !query.*\n") + } else { + Array.empty[String] + } + + queriesWithDebug.zipWithIndex.foreach { case ((sql, isDebug), i) => + val isCommand = try { + localSparkSession.sessionState.sqlParser.parsePlan(sql).isInstanceOf[Command] + } catch { + case _: ParseException => false + } + + if (isCommand) { + localSparkSession.sql(sql).collect() + } else if (isDebug) { + // Capture exception stacktrace if the query fails. + var exceptionTrace: Option[String] = None + val (schema, result) = handleExceptions { + try { + // Set a breakpoint here and evaluate `localSparkSession.sql(sql)` to get the + // DataFrame for ad-hoc debugging (e.g., df.queryExecution.analyzed). + getNormalizedQueryExecutionResult(localSparkSession, sql) + } catch { + case e: Throwable => + val sw = new StringWriter() + e.printStackTrace(new PrintWriter(sw)) + exceptionTrace = Some(sw.toString) + throw e + } + } + val output = ExecutionOutput( + sql = sql, + schema = Some(schema), + output = normalizeTestResults(result.mkString("\n"))) + + // Build consolidated debug output. + val debugOutput = new StringBuilder() + debugOutput.append(s"\n=== DEBUG: Query #$i ===") + debugOutput.append(s"\nSQL: $sql") + exceptionTrace.foreach { trace => + debugOutput.append(s"\n$trace") + } + + // Compare against golden file and append result. + var mismatch: Option[String] = None + if (goldenFileExists && + segments.length > segmentsPerQuery * i + segmentsPerQuery) { + val expected = ExecutionOutput( + segments(segmentsPerQuery * i + 1).trim, + Some(segments(segmentsPerQuery * i + 2).trim), + normalizeTestResults(segments(segmentsPerQuery * i + 3))) + + if (expected.sql != output.sql) { + debugOutput.append("\nGolden answer: no matching entry " + + "(SQL text differs, likely a new or moved query)") + } else if (expected.schema != output.schema) { + mismatch = Some(s"Schema did not match for query #$i\n${expected.sql}") + debugOutput.append(s"\nGolden answer: schema mismatch") + debugOutput.append(s"\n Expected: ${expected.schema.getOrElse("")}") + debugOutput.append(s"\n Actual: ${output.schema.getOrElse("")}") + } else if (expected.output != output.output) { + mismatch = Some(s"Result did not match for query #$i\n${expected.sql}") + debugOutput.append(s"\nGolden answer: result mismatch") + debugOutput.append(s"\n Expected:\n${expected.output}") + debugOutput.append(s"\n Actual:\n${output.output}") + } else { + debugOutput.append("\nGolden answer: matches") + } + } else { + debugOutput.append("\nGolden answer: no golden file to compare") + } + + // scalastyle:off println + println(debugOutput.toString) + // scalastyle:on println + + mismatch.foreach(fail(_)) + } + } + + if (requireTPCDSCases.contains(lowercaseTestCase)) { + tpcDSTableNamesToSchemas.foreach { case (name: String, _: String) => + localSparkSession.sql(s"DROP TABLE IF EXISTS $name") + } + } + + fail("Test is in debug mode. " + + "Remove --DEBUG markers from the input file before committing.") + } + + protected def runQueries( + queries: Seq[String], + testCase: TestCase, + sparkConfigSet: Seq[(String, String)]): Unit = { + // Create a local SparkSession to have stronger isolation between different test cases. + // This does not isolate catalog changes. + val localSparkSession = setupLocalSession(testCase, sparkConfigSet) + val lowercaseTestCase = testCase.name.toLowerCase(Locale.ROOT) + // Run the SQL queries preparing them for comparison. val outputs: Seq[QueryTestOutput] = queries.map { sql => testCase match { From a7990f30b2e22e30278d3cc09999d2044223c880 Mon Sep 17 00:00:00 2001 From: Kent Yao Date: Sat, 28 Feb 2026 23:10:43 +0800 Subject: [PATCH 098/130] [SPARK-55755][SQL][TESTS] Handle null ArithmeticException message on JDK 25 ### What changes were proposed in this pull request? On JDK 25, `Math.multiplyExact`/`Math.addExact` may throw `ArithmeticException` without a message (null instead of `"long overflow"`). This causes `NullPointerException` in tests that check the raw exception message via `.getMessage.contains(...)`. This PR: 1. **`MathUtils.withOverflow`**: Provides a fallback message `"Overflow"` when the raw JDK exception message is null, preventing null propagation into Spark error conditions (both interpreted and codegen paths). 2. **Test assertions**: Makes raw `ArithmeticException` message checks null-safe across: - `DateExpressionsSuite` (line 1825) - `CatalystTypeConvertersSuite` (line 305) - `DateTimeUtilsSuite` (line 835) - `IntervalUtilsSuite` (line 593) - `TimestampFormatterSuite` (lines 451, 453) ### Why are the changes needed? The JDK 25 scheduled CI build fails with: ``` java.lang.NullPointerException: Cannot invoke "String.contains(java.lang.CharSequence)" because "$org_scalatest_assert_macro_left" is null at DateExpressionsSuite.scala:1825 ``` See: https://github.com/apache/spark/actions/runs/22513372344/job/65226962993 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Existing tests pass on JDK 17. The `MathUtils.withOverflow` fix ensures non-null messages regardless of JDK version. ### Was this patch authored or co-authored using generative AI tooling? Yes, co-authored with GitHub Copilot. Closes #54553 from yaooqinn/fix-jdk25-long-overflow. Authored-by: Kent Yao Signed-off-by: Kent Yao --- .../org/apache/spark/sql/catalyst/util/MathUtils.scala | 7 +++++-- .../spark/sql/catalyst/CatalystTypeConvertersSuite.scala | 3 ++- .../sql/catalyst/expressions/DateExpressionsSuite.scala | 3 ++- .../spark/sql/catalyst/util/DateTimeUtilsSuite.scala | 3 ++- .../spark/sql/catalyst/util/IntervalUtilsSuite.scala | 3 ++- .../spark/sql/catalyst/util/TimestampFormatterSuite.scala | 5 +++-- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala index b113bccc74dfb..9f8ee7ae9319f 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala @@ -94,7 +94,9 @@ object MathUtils { f } catch { case e: ArithmeticException => - throw ExecutionErrors.arithmeticOverflowError(e.getMessage, hint, context) + // On JDK 25+, Math.*Exact may throw ArithmeticException without a message + val message = if (e.getMessage != null) e.getMessage else "Overflow" + throw ExecutionErrors.arithmeticOverflowError(message, hint, context) } } @@ -103,7 +105,8 @@ object MathUtils { |try { | $evalCode |} catch (ArithmeticException e) { - | throw QueryExecutionErrors.arithmeticOverflowError(e.getMessage(), "", $context); + | String msg = e.getMessage() != null ? e.getMessage() : "Overflow"; + | throw QueryExecutionErrors.arithmeticOverflowError(msg, "", $context); |} |""".stripMargin } diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala index 1b46825b34143..75ca908a941b5 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala @@ -302,7 +302,8 @@ class CatalystTypeConvertersSuite extends SparkFunSuite with SQLHelper { val errMsg = intercept[ArithmeticException] { IntervalUtils.durationToMicros(Duration.ofSeconds(Long.MaxValue, Long.MaxValue)) }.getMessage - assert(errMsg.contains("long overflow")) + // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a message + assert(errMsg == null || errMsg.contains("long overflow")) } test("SPARK-35726: Truncate java.time.Duration by fields of day-time interval type") { diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala index 4e942b8b3e518..dede06bdc4b6a 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala @@ -1822,7 +1822,8 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper { null) }.getCause assert(e.isInstanceOf[ArithmeticException]) - assert(e.getMessage.contains("long overflow")) + // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a message + assert(e.getMessage == null || e.getMessage.contains("long overflow")) checkEvaluation( TimestampAddInterval( diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala index b5b69a8340378..e7f29f547fc48 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala @@ -832,7 +832,8 @@ class DateTimeUtilsSuite extends SparkFunSuite with Matchers with SQLHelper { val msg = intercept[ArithmeticException] { DateTimeUtils.localDateTimeToMicros(dt) }.getMessage - assert(msg == "long overflow") + // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a message + assert(msg == null || msg == "long overflow") } } diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala index a87d599711cfc..c8a8a0c1444a1 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala @@ -590,7 +590,8 @@ class IntervalUtilsSuite extends SparkFunSuite with SQLHelper { val errMsg = intercept[ArithmeticException] { durationToMicros(Duration.ofDays(106751991 + 1)) }.getMessage - assert(errMsg.contains("long overflow")) + // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a message + assert(errMsg == null || errMsg.contains("long overflow")) } test("SPARK-34615: period to months") { diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala index 558d7eda78b4a..b1f6fefc2735e 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala @@ -448,9 +448,10 @@ class TimestampFormatterSuite extends DatetimeFormatterSuite { assert(formatter.parse("294247") === date(294247)) assert(formatter.parse("-290307") === date(-290307)) val e1 = intercept[ArithmeticException](formatter.parse("294248")) - assert(e1.getMessage === "long overflow") + // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a message + assert(e1.getMessage == null || e1.getMessage === "long overflow") val e2 = intercept[ArithmeticException](formatter.parse("-290308")) - assert(e2.getMessage === "long overflow") + assert(e2.getMessage == null || e2.getMessage === "long overflow") } test("SPARK-36418: default parsing w/o pattern") { From 3f54ac5c665c09cadc2334c7087361201444ffd2 Mon Sep 17 00:00:00 2001 From: Cheng Pan Date: Sun, 1 Mar 2026 01:45:22 +0800 Subject: [PATCH 099/130] Revert "[SPARK-55755][SQL][TESTS] Handle null ArithmeticException message on JDK 25" This reverts commit a7990f30b2e22e30278d3cc09999d2044223c880. --- .../org/apache/spark/sql/catalyst/util/MathUtils.scala | 7 ++----- .../spark/sql/catalyst/CatalystTypeConvertersSuite.scala | 3 +-- .../sql/catalyst/expressions/DateExpressionsSuite.scala | 3 +-- .../spark/sql/catalyst/util/DateTimeUtilsSuite.scala | 3 +-- .../spark/sql/catalyst/util/IntervalUtilsSuite.scala | 3 +-- .../spark/sql/catalyst/util/TimestampFormatterSuite.scala | 5 ++--- 6 files changed, 8 insertions(+), 16 deletions(-) diff --git a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala index 9f8ee7ae9319f..b113bccc74dfb 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala @@ -94,9 +94,7 @@ object MathUtils { f } catch { case e: ArithmeticException => - // On JDK 25+, Math.*Exact may throw ArithmeticException without a message - val message = if (e.getMessage != null) e.getMessage else "Overflow" - throw ExecutionErrors.arithmeticOverflowError(message, hint, context) + throw ExecutionErrors.arithmeticOverflowError(e.getMessage, hint, context) } } @@ -105,8 +103,7 @@ object MathUtils { |try { | $evalCode |} catch (ArithmeticException e) { - | String msg = e.getMessage() != null ? e.getMessage() : "Overflow"; - | throw QueryExecutionErrors.arithmeticOverflowError(msg, "", $context); + | throw QueryExecutionErrors.arithmeticOverflowError(e.getMessage(), "", $context); |} |""".stripMargin } diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala index 75ca908a941b5..1b46825b34143 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala @@ -302,8 +302,7 @@ class CatalystTypeConvertersSuite extends SparkFunSuite with SQLHelper { val errMsg = intercept[ArithmeticException] { IntervalUtils.durationToMicros(Duration.ofSeconds(Long.MaxValue, Long.MaxValue)) }.getMessage - // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a message - assert(errMsg == null || errMsg.contains("long overflow")) + assert(errMsg.contains("long overflow")) } test("SPARK-35726: Truncate java.time.Duration by fields of day-time interval type") { diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala index dede06bdc4b6a..4e942b8b3e518 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala @@ -1822,8 +1822,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper { null) }.getCause assert(e.isInstanceOf[ArithmeticException]) - // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a message - assert(e.getMessage == null || e.getMessage.contains("long overflow")) + assert(e.getMessage.contains("long overflow")) checkEvaluation( TimestampAddInterval( diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala index e7f29f547fc48..b5b69a8340378 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala @@ -832,8 +832,7 @@ class DateTimeUtilsSuite extends SparkFunSuite with Matchers with SQLHelper { val msg = intercept[ArithmeticException] { DateTimeUtils.localDateTimeToMicros(dt) }.getMessage - // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a message - assert(msg == null || msg == "long overflow") + assert(msg == "long overflow") } } diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala index c8a8a0c1444a1..a87d599711cfc 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala @@ -590,8 +590,7 @@ class IntervalUtilsSuite extends SparkFunSuite with SQLHelper { val errMsg = intercept[ArithmeticException] { durationToMicros(Duration.ofDays(106751991 + 1)) }.getMessage - // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a message - assert(errMsg == null || errMsg.contains("long overflow")) + assert(errMsg.contains("long overflow")) } test("SPARK-34615: period to months") { diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala index b1f6fefc2735e..558d7eda78b4a 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala @@ -448,10 +448,9 @@ class TimestampFormatterSuite extends DatetimeFormatterSuite { assert(formatter.parse("294247") === date(294247)) assert(formatter.parse("-290307") === date(-290307)) val e1 = intercept[ArithmeticException](formatter.parse("294248")) - // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a message - assert(e1.getMessage == null || e1.getMessage === "long overflow") + assert(e1.getMessage === "long overflow") val e2 = intercept[ArithmeticException](formatter.parse("-290308")) - assert(e2.getMessage == null || e2.getMessage === "long overflow") + assert(e2.getMessage === "long overflow") } test("SPARK-36418: default parsing w/o pattern") { From 81101bcd8a5eaaebe4f450f94c90da252ae9dbdb Mon Sep 17 00:00:00 2001 From: Dongjoon Hyun Date: Sat, 28 Feb 2026 13:36:58 -0800 Subject: [PATCH 100/130] [SPARK-55757][CORE] Improve `spark.task.cpus` validation ### What changes were proposed in this pull request? This PR aim to improve `spark.task.cpus` validation. ### Why are the changes needed? Currently, Apache Spark throws `java.lang.ArithmeticException` for the invalid `spark.task.cpus`. We had better provide actionable direction. **BEFORE** ``` $ bin/spark-shell -c spark.task.cpus=0 26/02/28 09:00:56 ERROR SparkContext: Error initializing SparkContext. java.lang.ArithmeticException: / by zero at org.apache.spark.resource.ResourceUtils$.warnOnWastedResources(ResourceUtils.scala:444) ``` **AFTER** ``` $ bin/spark-shell -c spark.task.cpus=0 ... 26/02/28 09:02:15 ERROR SparkContext: Error initializing SparkContext. org.apache.spark.SparkIllegalArgumentException: [INVALID_CONF_VALUE.REQUIREMENT] The value '0' in the config "spark.task.cpus" is invalid. The number of task CPUs must be positive. SQLSTATE: 22022 ``` ### Does this PR introduce _any_ user-facing change? This only changes the error message before starting Spark job. ### How was this patch tested? Pass the CIs with newly added test case. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity`. Closes #54559 from dongjoon-hyun/SPARK-55757. Authored-by: Dongjoon Hyun Signed-off-by: Dongjoon Hyun --- .../scala/org/apache/spark/internal/config/package.scala | 6 +++++- .../test/scala/org/apache/spark/SparkContextSuite.scala | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/core/src/main/scala/org/apache/spark/internal/config/package.scala b/core/src/main/scala/org/apache/spark/internal/config/package.scala index 331d798a3d768..1fcf37b6e06be 100644 --- a/core/src/main/scala/org/apache/spark/internal/config/package.scala +++ b/core/src/main/scala/org/apache/spark/internal/config/package.scala @@ -711,7 +711,11 @@ package object config { .createWithDefault(false) private[spark] val CPUS_PER_TASK = - ConfigBuilder("spark.task.cpus").version("0.5.0").intConf.createWithDefault(1) + ConfigBuilder("spark.task.cpus") + .version("0.5.0") + .intConf + .checkValue(_ > 0, "Number of cores to allocate for each task should be positive.") + .createWithDefault(1) private[spark] val DYN_ALLOCATION_ENABLED = ConfigBuilder("spark.dynamicAllocation.enabled") diff --git a/core/src/test/scala/org/apache/spark/SparkContextSuite.scala b/core/src/test/scala/org/apache/spark/SparkContextSuite.scala index 68bf9ca6a88cc..8dfb1ba67f1c1 100644 --- a/core/src/test/scala/org/apache/spark/SparkContextSuite.scala +++ b/core/src/test/scala/org/apache/spark/SparkContextSuite.scala @@ -1475,6 +1475,14 @@ class SparkContextSuite extends SparkFunSuite with LocalSparkContext with Eventu assert(!sc.conf.get(SparkLauncher.EXECUTOR_EXTRA_JAVA_OPTIONS).contains("-Dfoo=bar")) sc.stop() } + + test("SPARK-55757: Improve `spark.task.cpus` validation") { + val conf = new SparkConf().setAppName("test").setMaster("local").set(CPUS_PER_TASK, 0) + val m = intercept[SparkIllegalArgumentException] { + sc = new SparkContext(conf) + }.getMessage + assert(m.contains("Number of cores to allocate for each task should be positive.")) + } } object SparkContextSuite { From 392dd8dc39b2d6bb3fb341901cb27d4d7103dc34 Mon Sep 17 00:00:00 2001 From: Kent Yao Date: Sun, 1 Mar 2026 14:55:41 +0800 Subject: [PATCH 101/130] [SPARK-55753][UI] Upgrade Bootstrap from 4.6.2 to 5.3.8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this pull request? Upgrade the Spark Web UI from Bootstrap 4.6.2 (EOL Jan 2024) to Bootstrap 5.3.8: - Replace `bootstrap.bundle.min.js` and `bootstrap.min.css` with v5.3.8 - Replace `dataTables.bootstrap4` files with `dataTables.bootstrap5` - Migrate `data-toggle`/`data-target`/`data-placement`/`data-html`/`data-container` to `data-bs-*` prefix across all Scala, JS, and HTML template files - Migrate CSS classes: `mr-auto`→`me-auto`, `mr-2`→`me-2`, `float-right`→`float-end`, `form-inline`→`d-flex`, `form-group`→`mb-3` - Update tooltip initialization to use Bootstrap 5 `Tooltip` constructor instead of jQuery `.tooltip()` plugin - Update `docs/_layouts/global.html` for BS5 data attributes - jQuery is retained as it is still required by DataTables, dagre-d3, and custom Spark JS ### Why are the changes needed? Bootstrap 4.6.2 reached end-of-life in January 2024 and no longer receives security patches or bug fixes. Bootstrap 5 is the current LTS with active maintenance. ### Does this PR introduce _any_ user-facing change? No. The UI should look and behave identically. Bootstrap 5 is visually backward-compatible with Bootstrap 4. ### How was this patch tested? - All 12 Jest UI tests pass - Scalastyle passes - `core/compile` and `streaming/compile` succeed - `UIUtilsSuite` (8 tests) and `StoragePageSuite` (5 tests) pass - Live verification via spark-shell: all 4 main pages (`/`, `/jobs/`, `/stages/`, `/executors/`) serve correct BS5 markup with zero old BS4 attributes or CSS classes ### Was this patch authored or co-authored using generative AI tooling? Yes, GitHub Copilot was used. Closes #54552 from yaooqinn/ui-upgrade-bootstrap5. Authored-by: Kent Yao Signed-off-by: Kent Yao --- .../spark/ui/static/bootstrap.bundle.min.js | 6 +- .../apache/spark/ui/static/bootstrap.min.css | 9 ++- .../ui/static/dataTables.bootstrap4.min.css | 1 - .../ui/static/dataTables.bootstrap4.min.js | 4 -- .../ui/static/dataTables.bootstrap5.min.css | 5 ++ .../ui/static/dataTables.bootstrap5.min.js | 4 ++ .../ui/static/executorspage-template.html | 48 ++++++------- .../apache/spark/ui/static/executorspage.js | 4 +- .../spark/ui/static/historypage-template.html | 20 +++--- .../org/apache/spark/ui/static/historypage.js | 2 +- .../spark/ui/static/initialize-tooltips.js | 8 +-- .../apache/spark/ui/static/spark-dag-viz.js | 2 +- .../org/apache/spark/ui/static/stagepage.js | 60 ++++++++-------- .../spark/ui/static/stagespage-template.html | 2 +- .../apache/spark/ui/static/streaming-page.js | 9 ++- .../apache/spark/ui/static/timeline-view.js | 34 +++++---- .../deploy/master/ui/ApplicationPage.scala | 4 +- .../org/apache/spark/ui/PagedTable.scala | 69 ++++++++++--------- .../scala/org/apache/spark/ui/UIUtils.scala | 18 ++--- .../ui/exec/ExecutorThreadDumpPage.scala | 10 +-- .../apache/spark/ui/jobs/AllJobsPage.scala | 14 ++-- .../org/apache/spark/ui/jobs/JobPage.scala | 14 ++-- .../org/apache/spark/ui/jobs/PoolTable.scala | 5 +- .../org/apache/spark/ui/jobs/StagePage.scala | 10 +-- .../org/apache/spark/ui/jobs/StageTable.scala | 2 +- .../spark/ui/jobs/TaskThreadDumpPage.scala | 2 +- .../org/apache/spark/ui/storage/RDDPage.scala | 2 +- .../org/apache/spark/ui/UIUtilsSuite.scala | 2 +- .../spark/ui/storage/StoragePageSuite.scala | 2 +- dev/.rat-excludes | 4 +- dev/eslint.js | 3 + docs/_layouts/global.html | 12 ++-- .../connect/ui/SparkConnectServerPage.scala | 4 +- .../ui/SparkConnectServerSessionPage.scala | 2 +- .../ui/SparkConnectServerPageSuite.scala | 4 +- .../sql/execution/ui/AllExecutionsPage.scala | 2 +- .../sql/streaming/ui/StreamingQueryPage.scala | 2 +- .../thriftserver/ui/ThriftServerPage.scala | 4 +- .../ui/ThriftServerSessionPage.scala | 2 +- .../ui/ThriftServerPageSuite.scala | 4 +- .../spark/streaming/ui/StreamingPage.scala | 4 +- 41 files changed, 220 insertions(+), 199 deletions(-) delete mode 100644 core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.css delete mode 100644 core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.js create mode 100644 core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap5.min.css create mode 100644 core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap5.min.js diff --git a/core/src/main/resources/org/apache/spark/ui/static/bootstrap.bundle.min.js b/core/src/main/resources/org/apache/spark/ui/static/bootstrap.bundle.min.js index d7524d1056165..0b873693aec09 100644 --- a/core/src/main/resources/org/apache/spark/ui/static/bootstrap.bundle.min.js +++ b/core/src/main/resources/org/apache/spark/ui/static/bootstrap.bundle.min.js @@ -1,7 +1,7 @@ /*! - * Bootstrap v4.6.2 (https://getbootstrap.com/) - * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Bootstrap v5.3.8 (https://getbootstrap.com/) + * Copyright 2011-2025 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery")):"function"==typeof define&&define.amd?define(["exports","jquery"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap={},t.jQuery)}(this,(function(t,e){"use strict";function n(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var i=n(e);function o(t,e){for(var n=0;n=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};u.jQueryDetection(),i.default.fn.emulateTransitionEnd=function(t){var e=this,n=!1;return i.default(this).one(u.TRANSITION_END,(function(){n=!0})),setTimeout((function(){n||u.triggerTransitionEnd(e)}),t),this},i.default.event.special[u.TRANSITION_END]={bindType:l,delegateType:l,handle:function(t){if(i.default(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var f="bs.alert",d=i.default.fn.alert,c=function(){function t(t){this._element=t}var e=t.prototype;return e.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},e.dispose=function(){i.default.removeData(this._element,f),this._element=null},e._getRootElement=function(t){var e=u.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=i.default(t).closest(".alert")[0]),n},e._triggerCloseEvent=function(t){var e=i.default.Event("close.bs.alert");return i.default(t).trigger(e),e},e._removeElement=function(t){var e=this;if(i.default(t).removeClass("show"),i.default(t).hasClass("fade")){var n=u.getTransitionDurationFromElement(t);i.default(t).one(u.TRANSITION_END,(function(n){return e._destroyElement(t,n)})).emulateTransitionEnd(n)}else this._destroyElement(t)},e._destroyElement=function(t){i.default(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(e){return this.each((function(){var n=i.default(this),o=n.data(f);o||(o=new t(this),n.data(f,o)),"close"===e&&o[e](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},r(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();i.default(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',c._handleDismiss(new c)),i.default.fn.alert=c._jQueryInterface,i.default.fn.alert.Constructor=c,i.default.fn.alert.noConflict=function(){return i.default.fn.alert=d,c._jQueryInterface};var h="bs.button",p=i.default.fn.button,m="active",g='[data-toggle^="button"]',_='input:not([type="hidden"])',v=".btn",b=function(){function t(t){this._element=t,this.shouldAvoidTriggerChange=!1}var e=t.prototype;return e.toggle=function(){var t=!0,e=!0,n=i.default(this._element).closest('[data-toggle="buttons"]')[0];if(n){var o=this._element.querySelector(_);if(o){if("radio"===o.type)if(o.checked&&this._element.classList.contains(m))t=!1;else{var r=n.querySelector(".active");r&&i.default(r).removeClass(m)}t&&("checkbox"!==o.type&&"radio"!==o.type||(o.checked=!this._element.classList.contains(m)),this.shouldAvoidTriggerChange||i.default(o).trigger("change")),o.focus(),e=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(m)),t&&i.default(this._element).toggleClass(m))},e.dispose=function(){i.default.removeData(this._element,h),this._element=null},t._jQueryInterface=function(e,n){return this.each((function(){var o=i.default(this),r=o.data(h);r||(r=new t(this),o.data(h,r)),r.shouldAvoidTriggerChange=n,"toggle"===e&&r[e]()}))},r(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();i.default(document).on("click.bs.button.data-api",g,(function(t){var e=t.target,n=e;if(i.default(e).hasClass("btn")||(e=i.default(e).closest(v)[0]),!e||e.hasAttribute("disabled")||e.classList.contains("disabled"))t.preventDefault();else{var o=e.querySelector(_);if(o&&(o.hasAttribute("disabled")||o.classList.contains("disabled")))return void t.preventDefault();"INPUT"!==n.tagName&&"LABEL"===e.tagName||b._jQueryInterface.call(i.default(e),"toggle","INPUT"===n.tagName)}})).on("focus.bs.button.data-api blur.bs.button.data-api",g,(function(t){var e=i.default(t.target).closest(v)[0];i.default(e).toggleClass("focus",/^focus(in)?$/.test(t.type))})),i.default(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var e=t.prototype;return e.next=function(){this._isSliding||this._slide(C)},e.nextWhenVisible=function(){var t=i.default(this._element);!document.hidden&&t.is(":visible")&&"hidden"!==t.css("visibility")&&this.next()},e.prev=function(){this._isSliding||this._slide(S)},e.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(u.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},e.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},e.to=function(t){var e=this;this._activeElement=this._element.querySelector(D);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)i.default(this._element).one(N,(function(){return e.to(t)}));else{if(n===t)return this.pause(),void this.cycle();var o=t>n?C:S;this._slide(o,this._items[t])}},e.dispose=function(){i.default(this._element).off(".bs.carousel"),i.default.removeData(this._element,E),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},e._getConfig=function(t){return t=a({},A,t),u.typeCheckConfig(y,t,k),t},e._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},e._addEventListeners=function(){var t=this;this._config.keyboard&&i.default(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&i.default(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},e._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var e=function(e){t._pointerEvent&&I[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},n=function(e){t._pointerEvent&&I[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};i.default(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(i.default(this._element).on("pointerdown.bs.carousel",(function(t){return e(t)})),i.default(this._element).on("pointerup.bs.carousel",(function(t){return n(t)})),this._element.classList.add("pointer-event")):(i.default(this._element).on("touchstart.bs.carousel",(function(t){return e(t)})),i.default(this._element).on("touchmove.bs.carousel",(function(e){return function(e){t.touchDeltaX=e.originalEvent.touches&&e.originalEvent.touches.length>1?0:e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),i.default(this._element).on("touchend.bs.carousel",(function(t){return n(t)})))}},e._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},e._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},e._getItemByDirection=function(t,e){var n=t===C,i=t===S,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var a=(o+(t===S?-1:1))%this._items.length;return-1===a?this._items[this._items.length-1]:this._items[a]},e._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),o=this._getItemIndex(this._element.querySelector(D)),r=i.default.Event("slide.bs.carousel",{relatedTarget:t,direction:e,from:o,to:n});return i.default(this._element).trigger(r),r},e._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));i.default(e).removeClass(T);var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&i.default(n).addClass(T)}},e._updateInterval=function(){var t=this._activeElement||this._element.querySelector(D);if(t){var e=parseInt(t.getAttribute("data-interval"),10);e?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=e):this._config.interval=this._config.defaultInterval||this._config.interval}},e._slide=function(t,e){var n,o,r,a=this,s=this._element.querySelector(D),l=this._getItemIndex(s),f=e||s&&this._getItemByDirection(t,s),d=this._getItemIndex(f),c=Boolean(this._interval);if(t===C?(n="carousel-item-left",o="carousel-item-next",r="left"):(n="carousel-item-right",o="carousel-item-prev",r="right"),f&&i.default(f).hasClass(T))this._isSliding=!1;else if(!this._triggerSlideEvent(f,r).isDefaultPrevented()&&s&&f){this._isSliding=!0,c&&this.pause(),this._setActiveIndicatorElement(f),this._activeElement=f;var h=i.default.Event(N,{relatedTarget:f,direction:r,from:l,to:d});if(i.default(this._element).hasClass("slide")){i.default(f).addClass(o),u.reflow(f),i.default(s).addClass(n),i.default(f).addClass(n);var p=u.getTransitionDurationFromElement(s);i.default(s).one(u.TRANSITION_END,(function(){i.default(f).removeClass(n+" "+o).addClass(T),i.default(s).removeClass("active "+o+" "+n),a._isSliding=!1,setTimeout((function(){return i.default(a._element).trigger(h)}),0)})).emulateTransitionEnd(p)}else i.default(s).removeClass(T),i.default(f).addClass(T),this._isSliding=!1,i.default(this._element).trigger(h);c&&this.cycle()}},t._jQueryInterface=function(e){return this.each((function(){var n=i.default(this).data(E),o=a({},A,i.default(this).data());"object"==typeof e&&(o=a({},o,e));var r="string"==typeof e?e:o.slide;if(n||(n=new t(this,o),i.default(this).data(E,n)),"number"==typeof e)n.to(e);else if("string"==typeof r){if("undefined"==typeof n[r])throw new TypeError('No method named "'+r+'"');n[r]()}else o.interval&&o.ride&&(n.pause(),n.cycle())}))},t._dataApiClickHandler=function(e){var n=u.getSelectorFromElement(this);if(n){var o=i.default(n)[0];if(o&&i.default(o).hasClass("carousel")){var r=a({},i.default(o).data(),i.default(this).data()),s=this.getAttribute("data-slide-to");s&&(r.interval=!1),t._jQueryInterface.call(i.default(o),r),s&&i.default(o).data(E).to(s),e.preventDefault()}}},r(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return A}}]),t}();i.default(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",O._dataApiClickHandler),i.default(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),e=0,n=t.length;e0&&(this._selector=a,this._triggerArray.push(r))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var e=t.prototype;return e.toggle=function(){i.default(this._element).hasClass(P)?this.hide():this.show()},e.show=function(){var e,n,o=this;if(!(this._isTransitioning||i.default(this._element).hasClass(P)||(this._parent&&0===(e=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof o._config.parent?t.getAttribute("data-parent")===o._config.parent:t.classList.contains(F)}))).length&&(e=null),e&&(n=i.default(e).not(this._selector).data(j))&&n._isTransitioning))){var r=i.default.Event("show.bs.collapse");if(i.default(this._element).trigger(r),!r.isDefaultPrevented()){e&&(t._jQueryInterface.call(i.default(e).not(this._selector),"hide"),n||i.default(e).data(j,null));var a=this._getDimension();i.default(this._element).removeClass(F).addClass(R),this._element.style[a]=0,this._triggerArray.length&&i.default(this._triggerArray).removeClass(B).attr("aria-expanded",!0),this.setTransitioning(!0);var s="scroll"+(a[0].toUpperCase()+a.slice(1)),l=u.getTransitionDurationFromElement(this._element);i.default(this._element).one(u.TRANSITION_END,(function(){i.default(o._element).removeClass(R).addClass("collapse show"),o._element.style[a]="",o.setTransitioning(!1),i.default(o._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(l),this._element.style[a]=this._element[s]+"px"}}},e.hide=function(){var t=this;if(!this._isTransitioning&&i.default(this._element).hasClass(P)){var e=i.default.Event("hide.bs.collapse");if(i.default(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",u.reflow(this._element),i.default(this._element).addClass(R).removeClass("collapse show");var o=this._triggerArray.length;if(o>0)for(var r=0;r=0)return 1;return 0}(),Y=U&&window.Promise?function(t){var e=!1;return function(){e||(e=!0,window.Promise.resolve().then((function(){e=!1,t()})))}}:function(t){var e=!1;return function(){e||(e=!0,setTimeout((function(){e=!1,t()}),V))}};function z(t){return t&&"[object Function]"==={}.toString.call(t)}function K(t,e){if(1!==t.nodeType)return[];var n=t.ownerDocument.defaultView.getComputedStyle(t,null);return e?n[e]:n}function X(t){return"HTML"===t.nodeName?t:t.parentNode||t.host}function G(t){if(!t)return document.body;switch(t.nodeName){case"HTML":case"BODY":return t.ownerDocument.body;case"#document":return t.body}var e=K(t),n=e.overflow,i=e.overflowX,o=e.overflowY;return/(auto|scroll|overlay)/.test(n+o+i)?t:G(X(t))}function $(t){return t&&t.referenceNode?t.referenceNode:t}var J=U&&!(!window.MSInputMethodContext||!document.documentMode),Z=U&&/MSIE 10/.test(navigator.userAgent);function tt(t){return 11===t?J:10===t?Z:J||Z}function et(t){if(!t)return document.documentElement;for(var e=tt(10)?document.body:null,n=t.offsetParent||null;n===e&&t.nextElementSibling;)n=(t=t.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&"BODY"!==i&&"HTML"!==i?-1!==["TH","TD","TABLE"].indexOf(n.nodeName)&&"static"===K(n,"position")?et(n):n:t?t.ownerDocument.documentElement:document.documentElement}function nt(t){return null!==t.parentNode?nt(t.parentNode):t}function it(t,e){if(!(t&&t.nodeType&&e&&e.nodeType))return document.documentElement;var n=t.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_FOLLOWING,i=n?t:e,o=n?e:t,r=document.createRange();r.setStart(i,0),r.setEnd(o,0);var a,s,l=r.commonAncestorContainer;if(t!==l&&e!==l||i.contains(o))return"BODY"===(s=(a=l).nodeName)||"HTML"!==s&&et(a.firstElementChild)!==a?et(l):l;var u=nt(t);return u.host?it(u.host,e):it(t,nt(e).host)}function ot(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top",n="top"===e?"scrollTop":"scrollLeft",i=t.nodeName;if("BODY"===i||"HTML"===i){var o=t.ownerDocument.documentElement,r=t.ownerDocument.scrollingElement||o;return r[n]}return t[n]}function rt(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=ot(e,"top"),o=ot(e,"left"),r=n?-1:1;return t.top+=i*r,t.bottom+=i*r,t.left+=o*r,t.right+=o*r,t}function at(t,e){var n="x"===e?"Left":"Top",i="Left"===n?"Right":"Bottom";return parseFloat(t["border"+n+"Width"])+parseFloat(t["border"+i+"Width"])}function st(t,e,n,i){return Math.max(e["offset"+t],e["scroll"+t],n["client"+t],n["offset"+t],n["scroll"+t],tt(10)?parseInt(n["offset"+t])+parseInt(i["margin"+("Height"===t?"Top":"Left")])+parseInt(i["margin"+("Height"===t?"Bottom":"Right")]):0)}function lt(t){var e=t.body,n=t.documentElement,i=tt(10)&&getComputedStyle(n);return{height:st("Height",e,n,i),width:st("Width",e,n,i)}}var ut=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},ft=function(){function t(t,e){for(var n=0;n2&&void 0!==arguments[2]&&arguments[2],i=tt(10),o="HTML"===e.nodeName,r=pt(t),a=pt(e),s=G(t),l=K(e),u=parseFloat(l.borderTopWidth),f=parseFloat(l.borderLeftWidth);n&&o&&(a.top=Math.max(a.top,0),a.left=Math.max(a.left,0));var d=ht({top:r.top-a.top-u,left:r.left-a.left-f,width:r.width,height:r.height});if(d.marginTop=0,d.marginLeft=0,!i&&o){var c=parseFloat(l.marginTop),h=parseFloat(l.marginLeft);d.top-=u-c,d.bottom-=u-c,d.left-=f-h,d.right-=f-h,d.marginTop=c,d.marginLeft=h}return(i&&!n?e.contains(s):e===s&&"BODY"!==s.nodeName)&&(d=rt(d,e)),d}function gt(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.ownerDocument.documentElement,i=mt(t,n),o=Math.max(n.clientWidth,window.innerWidth||0),r=Math.max(n.clientHeight,window.innerHeight||0),a=e?0:ot(n),s=e?0:ot(n,"left"),l={top:a-i.top+i.marginTop,left:s-i.left+i.marginLeft,width:o,height:r};return ht(l)}function _t(t){var e=t.nodeName;if("BODY"===e||"HTML"===e)return!1;if("fixed"===K(t,"position"))return!0;var n=X(t);return!!n&&_t(n)}function vt(t){if(!t||!t.parentElement||tt())return document.documentElement;for(var e=t.parentElement;e&&"none"===K(e,"transform");)e=e.parentElement;return e||document.documentElement}function bt(t,e,n,i){var o=arguments.length>4&&void 0!==arguments[4]&&arguments[4],r={top:0,left:0},a=o?vt(t):it(t,$(e));if("viewport"===i)r=gt(a,o);else{var s=void 0;"scrollParent"===i?"BODY"===(s=G(X(e))).nodeName&&(s=t.ownerDocument.documentElement):s="window"===i?t.ownerDocument.documentElement:i;var l=mt(s,a,o);if("HTML"!==s.nodeName||_t(a))r=l;else{var u=lt(t.ownerDocument),f=u.height,d=u.width;r.top+=l.top-l.marginTop,r.bottom=f+l.top,r.left+=l.left-l.marginLeft,r.right=d+l.left}}var c="number"==typeof(n=n||0);return r.left+=c?n:n.left||0,r.top+=c?n:n.top||0,r.right-=c?n:n.right||0,r.bottom-=c?n:n.bottom||0,r}function yt(t){return t.width*t.height}function Et(t,e,n,i,o){var r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0;if(-1===t.indexOf("auto"))return t;var a=bt(n,i,r,o),s={top:{width:a.width,height:e.top-a.top},right:{width:a.right-e.right,height:a.height},bottom:{width:a.width,height:a.bottom-e.bottom},left:{width:e.left-a.left,height:a.height}},l=Object.keys(s).map((function(t){return ct({key:t},s[t],{area:yt(s[t])})})).sort((function(t,e){return e.area-t.area})),u=l.filter((function(t){var e=t.width,i=t.height;return e>=n.clientWidth&&i>=n.clientHeight})),f=u.length>0?u[0].key:l[0].key,d=t.split("-")[1];return f+(d?"-"+d:"")}function wt(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,o=i?vt(e):it(e,$(n));return mt(n,o,i)}function Tt(t){var e=t.ownerDocument.defaultView.getComputedStyle(t),n=parseFloat(e.marginTop||0)+parseFloat(e.marginBottom||0),i=parseFloat(e.marginLeft||0)+parseFloat(e.marginRight||0);return{width:t.offsetWidth+i,height:t.offsetHeight+n}}function Ct(t){var e={left:"right",right:"left",bottom:"top",top:"bottom"};return t.replace(/left|right|bottom|top/g,(function(t){return e[t]}))}function St(t,e,n){n=n.split("-")[0];var i=Tt(t),o={width:i.width,height:i.height},r=-1!==["right","left"].indexOf(n),a=r?"top":"left",s=r?"left":"top",l=r?"height":"width",u=r?"width":"height";return o[a]=e[a]+e[l]/2-i[l]/2,o[s]=n===s?e[s]-i[u]:e[Ct(s)],o}function Nt(t,e){return Array.prototype.find?t.find(e):t.filter(e)[0]}function Dt(t,e,n){return(void 0===n?t:t.slice(0,function(t,e,n){if(Array.prototype.findIndex)return t.findIndex((function(t){return t.name===n}));var i=Nt(t,(function(t){return t.name===n}));return t.indexOf(i)}(t,0,n))).forEach((function(t){t.function&&console.warn("`modifier.function` is deprecated, use `modifier.fn`!");var n=t.function||t.fn;t.enabled&&z(n)&&(e.offsets.popper=ht(e.offsets.popper),e.offsets.reference=ht(e.offsets.reference),e=n(e,t))})),e}function At(){if(!this.state.isDestroyed){var t={instance:this,styles:{},arrowStyles:{},attributes:{},flipped:!1,offsets:{}};t.offsets.reference=wt(this.state,this.popper,this.reference,this.options.positionFixed),t.placement=Et(this.options.placement,t.offsets.reference,this.popper,this.reference,this.options.modifiers.flip.boundariesElement,this.options.modifiers.flip.padding),t.originalPlacement=t.placement,t.positionFixed=this.options.positionFixed,t.offsets.popper=St(this.popper,t.offsets.reference,t.placement),t.offsets.popper.position=this.options.positionFixed?"fixed":"absolute",t=Dt(this.modifiers,t),this.state.isCreated?this.options.onUpdate(t):(this.state.isCreated=!0,this.options.onCreate(t))}}function kt(t,e){return t.some((function(t){var n=t.name;return t.enabled&&n===e}))}function It(t){for(var e=[!1,"ms","Webkit","Moz","O"],n=t.charAt(0).toUpperCase()+t.slice(1),i=0;i1&&void 0!==arguments[1]&&arguments[1],n=Qt.indexOf(t),i=Qt.slice(n+1).concat(Qt.slice(0,n));return e?i.reverse():i}var Ut={placement:"bottom",positionFixed:!1,eventsEnabled:!0,removeOnDestroy:!1,onCreate:function(){},onUpdate:function(){},modifiers:{shift:{order:100,enabled:!0,fn:function(t){var e=t.placement,n=e.split("-")[0],i=e.split("-")[1];if(i){var o=t.offsets,r=o.reference,a=o.popper,s=-1!==["bottom","top"].indexOf(n),l=s?"left":"top",u=s?"width":"height",f={start:dt({},l,r[l]),end:dt({},l,r[l]+r[u]-a[u])};t.offsets.popper=ct({},a,f[i])}return t}},offset:{order:200,enabled:!0,fn:function(t,e){var n,i=e.offset,o=t.placement,r=t.offsets,a=r.popper,s=r.reference,l=o.split("-")[0];return n=Rt(+i)?[+i,0]:function(t,e,n,i){var o=[0,0],r=-1!==["right","left"].indexOf(i),a=t.split(/(\+|\-)/).map((function(t){return t.trim()})),s=a.indexOf(Nt(a,(function(t){return-1!==t.search(/,|\s/)})));a[s]&&-1===a[s].indexOf(",")&&console.warn("Offsets separated by white space(s) are deprecated, use a comma (,) instead.");var l=/\s*,\s*|\s+/,u=-1!==s?[a.slice(0,s).concat([a[s].split(l)[0]]),[a[s].split(l)[1]].concat(a.slice(s+1))]:[a];return u=u.map((function(t,i){var o=(1===i?!r:r)?"height":"width",a=!1;return t.reduce((function(t,e){return""===t[t.length-1]&&-1!==["+","-"].indexOf(e)?(t[t.length-1]=e,a=!0,t):a?(t[t.length-1]+=e,a=!1,t):t.concat(e)}),[]).map((function(t){return function(t,e,n,i){var o=t.match(/((?:\-|\+)?\d*\.?\d*)(.*)/),r=+o[1],a=o[2];return r?0===a.indexOf("%")?ht("%p"===a?n:i)[e]/100*r:"vh"===a||"vw"===a?("vh"===a?Math.max(document.documentElement.clientHeight,window.innerHeight||0):Math.max(document.documentElement.clientWidth,window.innerWidth||0))/100*r:r:t}(t,o,e,n)}))})),u.forEach((function(t,e){t.forEach((function(n,i){Rt(n)&&(o[e]+=n*("-"===t[i-1]?-1:1))}))})),o}(i,a,s,l),"left"===l?(a.top+=n[0],a.left-=n[1]):"right"===l?(a.top+=n[0],a.left+=n[1]):"top"===l?(a.left+=n[0],a.top-=n[1]):"bottom"===l&&(a.left+=n[0],a.top+=n[1]),t.popper=a,t},offset:0},preventOverflow:{order:300,enabled:!0,fn:function(t,e){var n=e.boundariesElement||et(t.instance.popper);t.instance.reference===n&&(n=et(n));var i=It("transform"),o=t.instance.popper.style,r=o.top,a=o.left,s=o[i];o.top="",o.left="",o[i]="";var l=bt(t.instance.popper,t.instance.reference,e.padding,n,t.positionFixed);o.top=r,o.left=a,o[i]=s,e.boundaries=l;var u=e.priority,f=t.offsets.popper,d={primary:function(t){var n=f[t];return f[t]l[t]&&!e.escapeWithReference&&(i=Math.min(f[n],l[t]-("right"===t?f.width:f.height))),dt({},n,i)}};return u.forEach((function(t){var e=-1!==["left","top"].indexOf(t)?"primary":"secondary";f=ct({},f,d[e](t))})),t.offsets.popper=f,t},priority:["left","right","top","bottom"],padding:5,boundariesElement:"scrollParent"},keepTogether:{order:400,enabled:!0,fn:function(t){var e=t.offsets,n=e.popper,i=e.reference,o=t.placement.split("-")[0],r=Math.floor,a=-1!==["top","bottom"].indexOf(o),s=a?"right":"bottom",l=a?"left":"top",u=a?"width":"height";return n[s]r(i[s])&&(t.offsets.popper[l]=r(i[s])),t}},arrow:{order:500,enabled:!0,fn:function(t,e){var n;if(!Mt(t.instance.modifiers,"arrow","keepTogether"))return t;var i=e.element;if("string"==typeof i){if(!(i=t.instance.popper.querySelector(i)))return t}else if(!t.instance.popper.contains(i))return console.warn("WARNING: `arrow.element` must be child of its popper element!"),t;var o=t.placement.split("-")[0],r=t.offsets,a=r.popper,s=r.reference,l=-1!==["left","right"].indexOf(o),u=l?"height":"width",f=l?"Top":"Left",d=f.toLowerCase(),c=l?"left":"top",h=l?"bottom":"right",p=Tt(i)[u];s[h]-pa[h]&&(t.offsets.popper[d]+=s[d]+p-a[h]),t.offsets.popper=ht(t.offsets.popper);var m=s[d]+s[u]/2-p/2,g=K(t.instance.popper),_=parseFloat(g["margin"+f]),v=parseFloat(g["border"+f+"Width"]),b=m-t.offsets.popper[d]-_-v;return b=Math.max(Math.min(a[u]-p,b),0),t.arrowElement=i,t.offsets.arrow=(dt(n={},d,Math.round(b)),dt(n,c,""),n),t},element:"[x-arrow]"},flip:{order:600,enabled:!0,fn:function(t,e){if(kt(t.instance.modifiers,"inner"))return t;if(t.flipped&&t.placement===t.originalPlacement)return t;var n=bt(t.instance.popper,t.instance.reference,e.padding,e.boundariesElement,t.positionFixed),i=t.placement.split("-")[0],o=Ct(i),r=t.placement.split("-")[1]||"",a=[];switch(e.behavior){case"flip":a=[i,o];break;case"clockwise":a=Wt(i);break;case"counterclockwise":a=Wt(i,!0);break;default:a=e.behavior}return a.forEach((function(s,l){if(i!==s||a.length===l+1)return t;i=t.placement.split("-")[0],o=Ct(i);var u=t.offsets.popper,f=t.offsets.reference,d=Math.floor,c="left"===i&&d(u.right)>d(f.left)||"right"===i&&d(u.left)d(f.top)||"bottom"===i&&d(u.top)d(n.right),m=d(u.top)d(n.bottom),_="left"===i&&h||"right"===i&&p||"top"===i&&m||"bottom"===i&&g,v=-1!==["top","bottom"].indexOf(i),b=!!e.flipVariations&&(v&&"start"===r&&h||v&&"end"===r&&p||!v&&"start"===r&&m||!v&&"end"===r&&g),y=!!e.flipVariationsByContent&&(v&&"start"===r&&p||v&&"end"===r&&h||!v&&"start"===r&&g||!v&&"end"===r&&m),E=b||y;(c||_||E)&&(t.flipped=!0,(c||_)&&(i=a[l+1]),E&&(r=function(t){return"end"===t?"start":"start"===t?"end":t}(r)),t.placement=i+(r?"-"+r:""),t.offsets.popper=ct({},t.offsets.popper,St(t.instance.popper,t.offsets.reference,t.placement)),t=Dt(t.instance.modifiers,t,"flip"))})),t},behavior:"flip",padding:5,boundariesElement:"viewport",flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(t){var e=t.placement,n=e.split("-")[0],i=t.offsets,o=i.popper,r=i.reference,a=-1!==["left","right"].indexOf(n),s=-1===["top","left"].indexOf(n);return o[a?"left":"top"]=r[n]-(s?o[a?"width":"height"]:0),t.placement=Ct(e),t.offsets.popper=ht(o),t}},hide:{order:800,enabled:!0,fn:function(t){if(!Mt(t.instance.modifiers,"hide","preventOverflow"))return t;var e=t.offsets.reference,n=Nt(t.instance.modifiers,(function(t){return"preventOverflow"===t.name})).boundaries;if(e.bottomn.right||e.top>n.bottom||e.right2&&void 0!==arguments[2]?arguments[2]:{};ut(this,t),this.scheduleUpdate=function(){return requestAnimationFrame(i.update)},this.update=Y(this.update.bind(this)),this.options=ct({},t.Defaults,o),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=e&&e.jquery?e[0]:e,this.popper=n&&n.jquery?n[0]:n,this.options.modifiers={},Object.keys(ct({},t.Defaults.modifiers,o.modifiers)).forEach((function(e){i.options.modifiers[e]=ct({},t.Defaults.modifiers[e]||{},o.modifiers?o.modifiers[e]:{})})),this.modifiers=Object.keys(this.options.modifiers).map((function(t){return ct({name:t},i.options.modifiers[t])})).sort((function(t,e){return t.order-e.order})),this.modifiers.forEach((function(t){t.enabled&&z(t.onLoad)&&t.onLoad(i.reference,i.popper,i.options,t,i.state)})),this.update();var r=this.options.eventsEnabled;r&&this.enableEventListeners(),this.state.eventsEnabled=r}return ft(t,[{key:"update",value:function(){return At.call(this)}},{key:"destroy",value:function(){return Ot.call(this)}},{key:"enableEventListeners",value:function(){return Pt.call(this)}},{key:"disableEventListeners",value:function(){return Ft.call(this)}}]),t}();Vt.Utils=("undefined"!=typeof window?window:global).PopperUtils,Vt.placements=qt,Vt.Defaults=Ut;var Yt=Vt,zt="dropdown",Kt="bs.dropdown",Xt=i.default.fn[zt],Gt=new RegExp("38|40|27"),$t="disabled",Jt="show",Zt="dropdown-menu-right",te="hide.bs.dropdown",ee="hidden.bs.dropdown",ne="click.bs.dropdown.data-api",ie="keydown.bs.dropdown.data-api",oe='[data-toggle="dropdown"]',re=".dropdown-menu",ae={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic",popperConfig:null},se={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string",popperConfig:"(null|object)"},le=function(){function t(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var e=t.prototype;return e.toggle=function(){if(!this._element.disabled&&!i.default(this._element).hasClass($t)){var e=i.default(this._menu).hasClass(Jt);t._clearMenus(),e||this.show(!0)}},e.show=function(e){if(void 0===e&&(e=!1),!(this._element.disabled||i.default(this._element).hasClass($t)||i.default(this._menu).hasClass(Jt))){var n={relatedTarget:this._element},o=i.default.Event("show.bs.dropdown",n),r=t._getParentFromElement(this._element);if(i.default(r).trigger(o),!o.isDefaultPrevented()){if(!this._inNavbar&&e){if("undefined"==typeof Yt)throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");var a=this._element;"parent"===this._config.reference?a=r:u.isElement(this._config.reference)&&(a=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(a=this._config.reference[0])),"scrollParent"!==this._config.boundary&&i.default(r).addClass("position-static"),this._popper=new Yt(a,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===i.default(r).closest(".navbar-nav").length&&i.default(document.body).children().on("mouseover",null,i.default.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),i.default(this._menu).toggleClass(Jt),i.default(r).toggleClass(Jt).trigger(i.default.Event("shown.bs.dropdown",n))}}},e.hide=function(){if(!this._element.disabled&&!i.default(this._element).hasClass($t)&&i.default(this._menu).hasClass(Jt)){var e={relatedTarget:this._element},n=i.default.Event(te,e),o=t._getParentFromElement(this._element);i.default(o).trigger(n),n.isDefaultPrevented()||(this._popper&&this._popper.destroy(),i.default(this._menu).toggleClass(Jt),i.default(o).toggleClass(Jt).trigger(i.default.Event(ee,e)))}},e.dispose=function(){i.default.removeData(this._element,Kt),i.default(this._element).off(".bs.dropdown"),this._element=null,this._menu=null,null!==this._popper&&(this._popper.destroy(),this._popper=null)},e.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},e._addEventListeners=function(){var t=this;i.default(this._element).on("click.bs.dropdown",(function(e){e.preventDefault(),e.stopPropagation(),t.toggle()}))},e._getConfig=function(t){return t=a({},this.constructor.Default,i.default(this._element).data(),t),u.typeCheckConfig(zt,t,this.constructor.DefaultType),t},e._getMenuElement=function(){if(!this._menu){var e=t._getParentFromElement(this._element);e&&(this._menu=e.querySelector(re))}return this._menu},e._getPlacement=function(){var t=i.default(this._element.parentNode),e="bottom-start";return t.hasClass("dropup")?e=i.default(this._menu).hasClass(Zt)?"top-end":"top-start":t.hasClass("dropright")?e="right-start":t.hasClass("dropleft")?e="left-start":i.default(this._menu).hasClass(Zt)&&(e="bottom-end"),e},e._detectNavbar=function(){return i.default(this._element).closest(".navbar").length>0},e._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=a({},e.offsets,t._config.offset(e.offsets,t._element)),e}:e.offset=this._config.offset,e},e._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),a({},t,this._config.popperConfig)},t._jQueryInterface=function(e){return this.each((function(){var n=i.default(this).data(Kt);if(n||(n=new t(this,"object"==typeof e?e:null),i.default(this).data(Kt,n)),"string"==typeof e){if("undefined"==typeof n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},t._clearMenus=function(e){if(!e||3!==e.which&&("keyup"!==e.type||9===e.which))for(var n=[].slice.call(document.querySelectorAll(oe)),o=0,r=n.length;o0&&a--,40===e.which&&adocument.documentElement.clientHeight;n||(this._element.style.overflowY="hidden"),this._element.classList.add(pe);var o=u.getTransitionDurationFromElement(this._dialog);i.default(this._element).off(u.TRANSITION_END),i.default(this._element).one(u.TRANSITION_END,(function(){t._element.classList.remove(pe),n||i.default(t._element).one(u.TRANSITION_END,(function(){t._element.style.overflowY=""})).emulateTransitionEnd(t._element,o)})).emulateTransitionEnd(o),this._element.focus()}},e._showElement=function(t){var e=this,n=i.default(this._element).hasClass(ce),o=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),i.default(this._dialog).hasClass("modal-dialog-scrollable")&&o?o.scrollTop=0:this._element.scrollTop=0,n&&u.reflow(this._element),i.default(this._element).addClass(he),this._config.focus&&this._enforceFocus();var r=i.default.Event("shown.bs.modal",{relatedTarget:t}),a=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,i.default(e._element).trigger(r)};if(n){var s=u.getTransitionDurationFromElement(this._dialog);i.default(this._dialog).one(u.TRANSITION_END,a).emulateTransitionEnd(s)}else a()},e._enforceFocus=function(){var t=this;i.default(document).off(_e).on(_e,(function(e){document!==e.target&&t._element!==e.target&&0===i.default(t._element).has(e.target).length&&t._element.focus()}))},e._setEscapeEvent=function(){var t=this;this._isShown?i.default(this._element).on(ye,(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||i.default(this._element).off(ye)},e._setResizeEvent=function(){var t=this;this._isShown?i.default(window).on(ve,(function(e){return t.handleUpdate(e)})):i.default(window).off(ve)},e._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop((function(){i.default(document.body).removeClass(de),t._resetAdjustments(),t._resetScrollbar(),i.default(t._element).trigger(me)}))},e._removeBackdrop=function(){this._backdrop&&(i.default(this._backdrop).remove(),this._backdrop=null)},e._showBackdrop=function(t){var e=this,n=i.default(this._element).hasClass(ce)?ce:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",n&&this._backdrop.classList.add(n),i.default(this._backdrop).appendTo(document.body),i.default(this._element).on(be,(function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._triggerBackdropTransition():e.hide())})),n&&u.reflow(this._backdrop),i.default(this._backdrop).addClass(he),!t)return;if(!n)return void t();var o=u.getTransitionDurationFromElement(this._backdrop);i.default(this._backdrop).one(u.TRANSITION_END,t).emulateTransitionEnd(o)}else if(!this._isShown&&this._backdrop){i.default(this._backdrop).removeClass(he);var r=function(){e._removeBackdrop(),t&&t()};if(i.default(this._element).hasClass(ce)){var a=u.getTransitionDurationFromElement(this._backdrop);i.default(this._backdrop).one(u.TRANSITION_END,r).emulateTransitionEnd(a)}else r()}else t&&t()},e._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},e._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},e._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",customClass:"",sanitize:!0,sanitizeFn:null,whiteList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},We={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},Ue={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},Ve=function(){function t(t,e){if("undefined"==typeof Yt)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var e=t.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=i.default(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),i.default(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(i.default(this.getTipElement()).hasClass(Fe))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),i.default.removeData(this.element,this.constructor.DATA_KEY),i.default(this.element).off(this.constructor.EVENT_KEY),i.default(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&i.default(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===i.default(this.element).css("display"))throw new Error("Please use show on visible elements");var e=i.default.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){i.default(this.element).trigger(e);var n=u.findShadowRoot(this.element),o=i.default.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!o)return;var r=this.getTipElement(),a=u.getUID(this.constructor.NAME);r.setAttribute("id",a),this.element.setAttribute("aria-describedby",a),this.setContent(),this.config.animation&&i.default(r).addClass(Pe);var s="function"==typeof this.config.placement?this.config.placement.call(this,r,this.element):this.config.placement,l=this._getAttachment(s);this.addAttachmentClass(l);var f=this._getContainer();i.default(r).data(this.constructor.DATA_KEY,this),i.default.contains(this.element.ownerDocument.documentElement,this.tip)||i.default(r).appendTo(f),i.default(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new Yt(this.element,r,this._getPopperConfig(l)),i.default(r).addClass(Fe),i.default(r).addClass(this.config.customClass),"ontouchstart"in document.documentElement&&i.default(document.body).children().on("mouseover",null,i.default.noop);var d=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,i.default(t.element).trigger(t.constructor.Event.SHOWN),e===Be&&t._leave(null,t)};if(i.default(this.tip).hasClass(Pe)){var c=u.getTransitionDurationFromElement(this.tip);i.default(this.tip).one(u.TRANSITION_END,d).emulateTransitionEnd(c)}else d()}},e.hide=function(t){var e=this,n=this.getTipElement(),o=i.default.Event(this.constructor.Event.HIDE),r=function(){e._hoverState!==Re&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),i.default(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(i.default(this.element).trigger(o),!o.isDefaultPrevented()){if(i.default(n).removeClass(Fe),"ontouchstart"in document.documentElement&&i.default(document.body).children().off("mouseover",null,i.default.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,i.default(this.tip).hasClass(Pe)){var a=u.getTransitionDurationFromElement(n);i.default(n).one(u.TRANSITION_END,r).emulateTransitionEnd(a)}else r();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(t){i.default(this.getTipElement()).addClass("bs-tooltip-"+t)},e.getTipElement=function(){return this.tip=this.tip||i.default(this.config.template)[0],this.tip},e.setContent=function(){var t=this.getTipElement();this.setElementContent(i.default(t.querySelectorAll(".tooltip-inner")),this.getTitle()),i.default(t).removeClass("fade show")},e.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=ke(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?i.default(e).parent().is(t)||t.empty().append(e):t.text(i.default(e).text())},e.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},e._getPopperConfig=function(t){var e=this;return a({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},this.config.popperConfig)},e._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=a({},e.offsets,t.config.offset(e.offsets,t.element)),e}:e.offset=this.config.offset,e},e._getContainer=function(){return!1===this.config.container?document.body:u.isElement(this.config.container)?i.default(this.config.container):i.default(document).find(this.config.container)},e._getAttachment=function(t){return qe[t.toUpperCase()]},e._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)i.default(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==e){var n=e===He?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,o=e===He?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;i.default(t.element).on(n,t.config.selector,(function(e){return t._enter(e)})).on(o,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},i.default(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=a({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||i.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),i.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Me:He]=!0),i.default(e.getTipElement()).hasClass(Fe)||e._hoverState===Re?e._hoverState=Re:(clearTimeout(e._timeout),e._hoverState=Re,e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){e._hoverState===Re&&e.show()}),e.config.delay.show):e.show())},e._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||i.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),i.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Me:He]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=Be,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){e._hoverState===Be&&e.hide()}),e.config.delay.hide):e.hide())},e._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},e._getConfig=function(t){var e=i.default(this.element).data();return Object.keys(e).forEach((function(t){-1!==Le.indexOf(t)&&delete e[t]})),"number"==typeof(t=a({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),u.typeCheckConfig(Ie,t,this.constructor.DefaultType),t.sanitize&&(t.template=ke(t.template,t.whiteList,t.sanitizeFn)),t},e._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},e._cleanTipClass=function(){var t=i.default(this.getTipElement()),e=t.attr("class").match(je);null!==e&&e.length&&t.removeClass(e.join(""))},e._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},e._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(i.default(t).removeClass(Pe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},t._jQueryInterface=function(e){return this.each((function(){var n=i.default(this),o=n.data(Oe),r="object"==typeof e&&e;if((o||!/dispose|hide/.test(e))&&(o||(o=new t(this,r),n.data(Oe,o)),"string"==typeof e)){if("undefined"==typeof o[e])throw new TypeError('No method named "'+e+'"');o[e]()}}))},r(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return Qe}},{key:"NAME",get:function(){return Ie}},{key:"DATA_KEY",get:function(){return Oe}},{key:"Event",get:function(){return Ue}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return We}}]),t}();i.default.fn.tooltip=Ve._jQueryInterface,i.default.fn.tooltip.Constructor=Ve,i.default.fn.tooltip.noConflict=function(){return i.default.fn.tooltip=xe,Ve._jQueryInterface};var Ye="bs.popover",ze=i.default.fn.popover,Ke=new RegExp("(^|\\s)bs-popover\\S+","g"),Xe=a({},Ve.Default,{placement:"right",trigger:"click",content:"",template:''}),Ge=a({},Ve.DefaultType,{content:"(string|element|function)"}),$e={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},Je=function(t){var e,n;function o(){return t.apply(this,arguments)||this}n=t,(e=o).prototype=Object.create(n.prototype),e.prototype.constructor=e,s(e,n);var a=o.prototype;return a.isWithContent=function(){return this.getTitle()||this._getContent()},a.addAttachmentClass=function(t){i.default(this.getTipElement()).addClass("bs-popover-"+t)},a.getTipElement=function(){return this.tip=this.tip||i.default(this.config.template)[0],this.tip},a.setContent=function(){var t=i.default(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(".popover-body"),e),t.removeClass("fade show")},a._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},a._cleanTipClass=function(){var t=i.default(this.getTipElement()),e=t.attr("class").match(Ke);null!==e&&e.length>0&&t.removeClass(e.join(""))},o._jQueryInterface=function(t){return this.each((function(){var e=i.default(this).data(Ye),n="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new o(this,n),i.default(this).data(Ye,e)),"string"==typeof t)){if("undefined"==typeof e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},r(o,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return Xe}},{key:"NAME",get:function(){return"popover"}},{key:"DATA_KEY",get:function(){return Ye}},{key:"Event",get:function(){return $e}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return Ge}}]),o}(Ve);i.default.fn.popover=Je._jQueryInterface,i.default.fn.popover.Constructor=Je,i.default.fn.popover.noConflict=function(){return i.default.fn.popover=ze,Je._jQueryInterface};var Ze="scrollspy",tn="bs.scrollspy",en=i.default.fn[Ze],nn="active",on="position",rn=".nav, .list-group",an={offset:10,method:"auto",target:""},sn={offset:"number",method:"string",target:"(string|element)"},ln=function(){function t(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,i.default(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return n._process(t)})),this.refresh(),this._process()}var e=t.prototype;return e.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?"offset":on,n="auto"===this._config.method?e:this._config.method,o=n===on?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var e,r=u.getSelectorFromElement(t);if(r&&(e=document.querySelector(r)),e){var a=e.getBoundingClientRect();if(a.width||a.height)return[i.default(e)[n]().top+o,r]}return null})).filter(Boolean).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},e.dispose=function(){i.default.removeData(this._element,tn),i.default(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},e._getConfig=function(t){if("string"!=typeof(t=a({},an,"object"==typeof t&&t?t:{})).target&&u.isElement(t.target)){var e=i.default(t.target).attr("id");e||(e=u.getUID(Ze),i.default(t.target).attr("id",e)),t.target="#"+e}return u.typeCheckConfig(Ze,t,sn),t},e._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},e._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},e._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},e._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;)this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t li > .active",gn=function(){function t(t){this._element=t}var e=t.prototype;return e.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&i.default(this._element).hasClass(dn)||i.default(this._element).hasClass("disabled")||this._element.hasAttribute("disabled"))){var e,n,o=i.default(this._element).closest(".nav, .list-group")[0],r=u.getSelectorFromElement(this._element);if(o){var a="UL"===o.nodeName||"OL"===o.nodeName?mn:pn;n=(n=i.default.makeArray(i.default(o).find(a)))[n.length-1]}var s=i.default.Event("hide.bs.tab",{relatedTarget:this._element}),l=i.default.Event("show.bs.tab",{relatedTarget:n});if(n&&i.default(n).trigger(s),i.default(this._element).trigger(l),!l.isDefaultPrevented()&&!s.isDefaultPrevented()){r&&(e=document.querySelector(r)),this._activate(this._element,o);var f=function(){var e=i.default.Event("hidden.bs.tab",{relatedTarget:t._element}),o=i.default.Event("shown.bs.tab",{relatedTarget:n});i.default(n).trigger(e),i.default(t._element).trigger(o)};e?this._activate(e,e.parentNode,f):f()}}},e.dispose=function(){i.default.removeData(this._element,un),this._element=null},e._activate=function(t,e,n){var o=this,r=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?i.default(e).children(pn):i.default(e).find(mn))[0],a=n&&r&&i.default(r).hasClass(cn),s=function(){return o._transitionComplete(t,r,n)};if(r&&a){var l=u.getTransitionDurationFromElement(r);i.default(r).removeClass(hn).one(u.TRANSITION_END,s).emulateTransitionEnd(l)}else s()},e._transitionComplete=function(t,e,n){if(e){i.default(e).removeClass(dn);var o=i.default(e.parentNode).find("> .dropdown-menu .active")[0];o&&i.default(o).removeClass(dn),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}i.default(t).addClass(dn),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),u.reflow(t),t.classList.contains(cn)&&t.classList.add(hn);var r=t.parentNode;if(r&&"LI"===r.nodeName&&(r=r.parentNode),r&&i.default(r).hasClass("dropdown-menu")){var a=i.default(t).closest(".dropdown")[0];if(a){var s=[].slice.call(a.querySelectorAll(".dropdown-toggle"));i.default(s).addClass(dn)}t.setAttribute("aria-expanded",!0)}n&&n()},t._jQueryInterface=function(e){return this.each((function(){var n=i.default(this),o=n.data(un);if(o||(o=new t(this),n.data(un,o)),"string"==typeof e){if("undefined"==typeof o[e])throw new TypeError('No method named "'+e+'"');o[e]()}}))},r(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();i.default(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),gn._jQueryInterface.call(i.default(this),"show")})),i.default.fn.tab=gn._jQueryInterface,i.default.fn.tab.Constructor=gn,i.default.fn.tab.noConflict=function(){return i.default.fn.tab=fn,gn._jQueryInterface};var _n="bs.toast",vn=i.default.fn.toast,bn="hide",yn="show",En="showing",wn="click.dismiss.bs.toast",Tn={animation:!0,autohide:!0,delay:500},Cn={animation:"boolean",autohide:"boolean",delay:"number"},Sn=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var e=t.prototype;return e.show=function(){var t=this,e=i.default.Event("show.bs.toast");if(i.default(this._element).trigger(e),!e.isDefaultPrevented()){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var n=function(){t._element.classList.remove(En),t._element.classList.add(yn),i.default(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove(bn),u.reflow(this._element),this._element.classList.add(En),this._config.animation){var o=u.getTransitionDurationFromElement(this._element);i.default(this._element).one(u.TRANSITION_END,n).emulateTransitionEnd(o)}else n()}},e.hide=function(){if(this._element.classList.contains(yn)){var t=i.default.Event("hide.bs.toast");i.default(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},e.dispose=function(){this._clearTimeout(),this._element.classList.contains(yn)&&this._element.classList.remove(yn),i.default(this._element).off(wn),i.default.removeData(this._element,_n),this._element=null,this._config=null},e._getConfig=function(t){return t=a({},Tn,i.default(this._element).data(),"object"==typeof t&&t?t:{}),u.typeCheckConfig("toast",t,this.constructor.DefaultType),t},e._setListeners=function(){var t=this;i.default(this._element).on(wn,'[data-dismiss="toast"]',(function(){return t.hide()}))},e._close=function(){var t=this,e=function(){t._element.classList.add(bn),i.default(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove(yn),this._config.animation){var n=u.getTransitionDurationFromElement(this._element);i.default(this._element).one(u.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},e._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},t._jQueryInterface=function(e){return this.each((function(){var n=i.default(this),o=n.data(_n);if(o||(o=new t(this,"object"==typeof e&&e),n.data(_n,o)),"string"==typeof e){if("undefined"==typeof o[e])throw new TypeError('No method named "'+e+'"');o[e](this)}}))},r(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"DefaultType",get:function(){return Cn}},{key:"Default",get:function(){return Tn}}]),t}();i.default.fn.toast=Sn._jQueryInterface,i.default.fn.toast.Constructor=Sn,i.default.fn.toast.noConflict=function(){return i.default.fn.toast=vn,Sn._jQueryInterface},t.Alert=c,t.Button=b,t.Carousel=O,t.Collapse=W,t.Dropdown=le,t.Modal=Se,t.Popover=Je,t.Scrollspy=ln,t.Tab=gn,t.Toast=Sn,t.Tooltip=Ve,t.Util=u,Object.defineProperty(t,"__esModule",{value:!0})})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,function(){"use strict";const t=new Map,e={set(e,i,n){t.has(e)||t.set(e,new Map);const s=t.get(e);s.has(i)||0===s.size?s.set(i,n):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(s.keys())[0]}.`)},get:(e,i)=>t.has(e)&&t.get(e).get(i)||null,remove(e,i){if(!t.has(e))return;const n=t.get(e);n.delete(i),0===n.size&&t.delete(e)}},i="transitionend",n=t=>(t&&window.CSS&&window.CSS.escape&&(t=t.replace(/#([^\s"#']+)/g,(t,e)=>`#${CSS.escape(e)}`)),t),s=t=>null==t?`${t}`:Object.prototype.toString.call(t).match(/\s([a-z]+)/i)[1].toLowerCase(),o=t=>{t.dispatchEvent(new Event(i))},r=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),a=t=>r(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(n(t)):null,l=t=>{if(!r(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},c=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),h=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?h(t.parentNode):null},d=()=>{},u=t=>{t.offsetHeight},f=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,p=[],m=()=>"rtl"===document.documentElement.dir,g=t=>{var e;e=()=>{const e=f();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(p.length||document.addEventListener("DOMContentLoaded",()=>{for(const t of p)t()}),p.push(e)):e()},_=(t,e=[],i=t)=>"function"==typeof t?t.call(...e):i,b=(t,e,n=!0)=>{if(!n)return void _(t);const s=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(e)+5;let r=!1;const a=({target:n})=>{n===e&&(r=!0,e.removeEventListener(i,a),_(t))};e.addEventListener(i,a),setTimeout(()=>{r||o(e)},s)},v=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},y=/[^.]*(?=\..*)\.|.*/,w=/\..*/,A=/::\d+$/,E={};let T=1;const C={mouseenter:"mouseover",mouseleave:"mouseout"},O=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function x(t,e){return e&&`${e}::${T++}`||t.uidEvent||T++}function k(t){const e=x(t);return t.uidEvent=e,E[e]=E[e]||{},E[e]}function L(t,e,i=null){return Object.values(t).find(t=>t.callable===e&&t.delegationSelector===i)}function S(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=N(t);return O.has(o)||(o=t),[n,s,o]}function D(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=S(e,i,n);if(e in C){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=k(t),c=l[a]||(l[a]={}),h=L(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=x(r,e.replace(y,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return j(s,{delegateTarget:r}),n.oneOff&&P.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return j(n,{delegateTarget:t}),i.oneOff&&P.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function $(t,e,i,n,s){const o=L(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function I(t,e,i,n){const s=e[i]||{};for(const[o,r]of Object.entries(s))o.includes(n)&&$(t,e,i,r.callable,r.delegationSelector)}function N(t){return t=t.replace(w,""),C[t]||t}const P={on(t,e,i,n){D(t,e,i,n,!1)},one(t,e,i,n){D(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=S(e,i,n),a=r!==e,l=k(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))I(t,l,i,e.slice(1));for(const[i,n]of Object.entries(c)){const s=i.replace(A,"");a&&!e.includes(s)||$(t,l,r,n.callable,n.delegationSelector)}}else{if(!Object.keys(c).length)return;$(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=f();let s=null,o=!0,r=!0,a=!1;e!==N(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());const l=j(new Event(e,{bubbles:o,cancelable:!0}),i);return a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function j(t,e={}){for(const[i,n]of Object.entries(e))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}function M(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function F(t){return t.replace(/[A-Z]/g,t=>`-${t.toLowerCase()}`)}const H={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${F(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${F(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter(t=>t.startsWith("bs")&&!t.startsWith("bsConfig"));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1),e[i]=M(t.dataset[n])}return e},getDataAttribute:(t,e)=>M(t.getAttribute(`data-bs-${F(e)}`))};class W{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=r(e)?H.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...r(e)?H.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const[i,n]of Object.entries(e)){const e=t[i],o=r(e)?"element":s(e);if(!new RegExp(n).test(o))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${i}" provided type "${o}" but expected type "${n}".`)}}}class B extends W{constructor(t,i){super(),(t=a(t))&&(this._element=t,this._config=this._getConfig(i),e.set(this._element,this.constructor.DATA_KEY,this))}dispose(){e.remove(this._element,this.constructor.DATA_KEY),P.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){b(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return e.get(a(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.3.8"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const z=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return e?e.split(",").map(t=>n(t)).join(","):null},R={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter(t=>t.matches(e)),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map(t=>`${t}:not([tabindex^="-"])`).join(",");return this.find(e,t).filter(t=>!c(t)&&l(t))},getSelectorFromElement(t){const e=z(t);return e&&R.findOne(e)?e:null},getElementFromSelector(t){const e=z(t);return e?R.findOne(e):null},getMultipleElementsFromSelector(t){const e=z(t);return e?R.find(e):[]}},q=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,n=t.NAME;P.on(document,i,`[data-bs-dismiss="${n}"]`,function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),c(this))return;const s=R.getElementFromSelector(this)||this.closest(`.${n}`);t.getOrCreateInstance(s)[e]()})},V=".bs.alert",K=`close${V}`,Q=`closed${V}`;class X extends B{static get NAME(){return"alert"}close(){if(P.trigger(this._element,K).defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback(()=>this._destroyElement(),this._element,t)}_destroyElement(){this._element.remove(),P.trigger(this._element,Q),this.dispose()}static jQueryInterface(t){return this.each(function(){const e=X.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}})}}q(X,"close"),g(X);const Y='[data-bs-toggle="button"]';class U extends B{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each(function(){const e=U.getOrCreateInstance(this);"toggle"===t&&e[t]()})}}P.on(document,"click.bs.button.data-api",Y,t=>{t.preventDefault();const e=t.target.closest(Y);U.getOrCreateInstance(e).toggle()}),g(U);const G=".bs.swipe",J=`touchstart${G}`,Z=`touchmove${G}`,tt=`touchend${G}`,et=`pointerdown${G}`,it=`pointerup${G}`,nt={endCallback:null,leftCallback:null,rightCallback:null},st={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class ot extends W{constructor(t,e){super(),this._element=t,t&&ot.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return nt}static get DefaultType(){return st}static get NAME(){return"swipe"}dispose(){P.off(this._element,G)}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),_(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&_(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(P.on(this._element,et,t=>this._start(t)),P.on(this._element,it,t=>this._end(t)),this._element.classList.add("pointer-event")):(P.on(this._element,J,t=>this._start(t)),P.on(this._element,Z,t=>this._move(t)),P.on(this._element,tt,t=>this._end(t)))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const rt=".bs.carousel",at=".data-api",lt="ArrowLeft",ct="ArrowRight",ht="next",dt="prev",ut="left",ft="right",pt=`slide${rt}`,mt=`slid${rt}`,gt=`keydown${rt}`,_t=`mouseenter${rt}`,bt=`mouseleave${rt}`,vt=`dragstart${rt}`,yt=`load${rt}${at}`,wt=`click${rt}${at}`,At="carousel",Et="active",Tt=".active",Ct=".carousel-item",Ot=Tt+Ct,xt={[lt]:ft,[ct]:ut},kt={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},Lt={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class St extends B{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=R.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===At&&this.cycle()}static get Default(){return kt}static get DefaultType(){return Lt}static get NAME(){return"carousel"}next(){this._slide(ht)}nextWhenVisible(){!document.hidden&&l(this._element)&&this.next()}prev(){this._slide(dt)}pause(){this._isSliding&&o(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval(()=>this.nextWhenVisible(),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?P.one(this._element,mt,()=>this.cycle()):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void P.one(this._element,mt,()=>this.to(t));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?ht:dt;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&P.on(this._element,gt,t=>this._keydown(t)),"hover"===this._config.pause&&(P.on(this._element,_t,()=>this.pause()),P.on(this._element,bt,()=>this._maybeEnableCycle())),this._config.touch&&ot.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of R.find(".carousel-item img",this._element))P.on(t,vt,t=>t.preventDefault());const t={leftCallback:()=>this._slide(this._directionToOrder(ut)),rightCallback:()=>this._slide(this._directionToOrder(ft)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout(()=>this._maybeEnableCycle(),500+this._config.interval))}};this._swipeHelper=new ot(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=xt[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=R.findOne(Tt,this._indicatorsElement);e.classList.remove(Et),e.removeAttribute("aria-current");const i=R.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(Et),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===ht,s=e||v(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>P.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r(pt).defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),u(s),i.classList.add(l),s.classList.add(l),this._queueCallback(()=>{s.classList.remove(l,c),s.classList.add(Et),i.classList.remove(Et,c,l),this._isSliding=!1,r(mt)},i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return R.findOne(Ot,this._element)}_getItems(){return R.find(Ct,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return m()?t===ut?dt:ht:t===ut?ht:dt}_orderToDirection(t){return m()?t===dt?ut:ft:t===dt?ft:ut}static jQueryInterface(t){return this.each(function(){const e=St.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)})}}P.on(document,wt,"[data-bs-slide], [data-bs-slide-to]",function(t){const e=R.getElementFromSelector(this);if(!e||!e.classList.contains(At))return;t.preventDefault();const i=St.getOrCreateInstance(e),n=this.getAttribute("data-bs-slide-to");return n?(i.to(n),void i._maybeEnableCycle()):"next"===H.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())}),P.on(window,yt,()=>{const t=R.find('[data-bs-ride="carousel"]');for(const e of t)St.getOrCreateInstance(e)}),g(St);const Dt=".bs.collapse",$t=`show${Dt}`,It=`shown${Dt}`,Nt=`hide${Dt}`,Pt=`hidden${Dt}`,jt=`click${Dt}.data-api`,Mt="show",Ft="collapse",Ht="collapsing",Wt=`:scope .${Ft} .${Ft}`,Bt='[data-bs-toggle="collapse"]',zt={parent:null,toggle:!0},Rt={parent:"(null|element)",toggle:"boolean"};class qt extends B{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const i=R.find(Bt);for(const t of i){const e=R.getSelectorFromElement(t),i=R.find(e).filter(t=>t===this._element);null!==e&&i.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return zt}static get DefaultType(){return Rt}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter(t=>t!==this._element).map(t=>qt.getOrCreateInstance(t,{toggle:!1}))),t.length&&t[0]._isTransitioning)return;if(P.trigger(this._element,$t).defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(Ft),this._element.classList.add(Ht),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback(()=>{this._isTransitioning=!1,this._element.classList.remove(Ht),this._element.classList.add(Ft,Mt),this._element.style[e]="",P.trigger(this._element,It)},this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(P.trigger(this._element,Nt).defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,u(this._element),this._element.classList.add(Ht),this._element.classList.remove(Ft,Mt);for(const t of this._triggerArray){const e=R.getElementFromSelector(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback(()=>{this._isTransitioning=!1,this._element.classList.remove(Ht),this._element.classList.add(Ft),P.trigger(this._element,Pt)},this._element,!0)}_isShown(t=this._element){return t.classList.contains(Mt)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=a(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(Bt);for(const e of t){const t=R.getElementFromSelector(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=R.find(Wt,this._config.parent);return R.find(t,this._config.parent).filter(t=>!e.includes(t))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each(function(){const i=qt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}})}}P.on(document,jt,Bt,function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();for(const t of R.getMultipleElementsFromSelector(this))qt.getOrCreateInstance(t,{toggle:!1}).toggle()}),g(qt);var Vt="top",Kt="bottom",Qt="right",Xt="left",Yt="auto",Ut=[Vt,Kt,Qt,Xt],Gt="start",Jt="end",Zt="clippingParents",te="viewport",ee="popper",ie="reference",ne=Ut.reduce(function(t,e){return t.concat([e+"-"+Gt,e+"-"+Jt])},[]),se=[].concat(Ut,[Yt]).reduce(function(t,e){return t.concat([e,e+"-"+Gt,e+"-"+Jt])},[]),oe="beforeRead",re="read",ae="afterRead",le="beforeMain",ce="main",he="afterMain",de="beforeWrite",ue="write",fe="afterWrite",pe=[oe,re,ae,le,ce,he,de,ue,fe];function me(t){return t?(t.nodeName||"").toLowerCase():null}function ge(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function _e(t){return t instanceof ge(t).Element||t instanceof Element}function be(t){return t instanceof ge(t).HTMLElement||t instanceof HTMLElement}function ve(t){return"undefined"!=typeof ShadowRoot&&(t instanceof ge(t).ShadowRoot||t instanceof ShadowRoot)}const ye={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach(function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];be(s)&&me(s)&&(Object.assign(s.style,i),Object.keys(n).forEach(function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)}))})},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach(function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce(function(t,e){return t[e]="",t},{});be(n)&&me(n)&&(Object.assign(n.style,o),Object.keys(s).forEach(function(t){n.removeAttribute(t)}))})}},requires:["computeStyles"]};function we(t){return t.split("-")[0]}var Ae=Math.max,Ee=Math.min,Te=Math.round;function Ce(){var t=navigator.userAgentData;return null!=t&&t.brands&&Array.isArray(t.brands)?t.brands.map(function(t){return t.brand+"/"+t.version}).join(" "):navigator.userAgent}function Oe(){return!/^((?!chrome|android).)*safari/i.test(Ce())}function xe(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&be(t)&&(s=t.offsetWidth>0&&Te(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&Te(n.height)/t.offsetHeight||1);var r=(_e(t)?ge(t):window).visualViewport,a=!Oe()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function ke(t){var e=xe(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Le(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&ve(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function Se(t){return ge(t).getComputedStyle(t)}function De(t){return["table","td","th"].indexOf(me(t))>=0}function $e(t){return((_e(t)?t.ownerDocument:t.document)||window.document).documentElement}function Ie(t){return"html"===me(t)?t:t.assignedSlot||t.parentNode||(ve(t)?t.host:null)||$e(t)}function Ne(t){return be(t)&&"fixed"!==Se(t).position?t.offsetParent:null}function Pe(t){for(var e=ge(t),i=Ne(t);i&&De(i)&&"static"===Se(i).position;)i=Ne(i);return i&&("html"===me(i)||"body"===me(i)&&"static"===Se(i).position)?e:i||function(t){var e=/firefox/i.test(Ce());if(/Trident/i.test(Ce())&&be(t)&&"fixed"===Se(t).position)return null;var i=Ie(t);for(ve(i)&&(i=i.host);be(i)&&["html","body"].indexOf(me(i))<0;){var n=Se(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function je(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function Me(t,e,i){return Ae(t,Ee(e,i))}function Fe(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function He(t,e){return e.reduce(function(e,i){return e[i]=t,e},{})}const We={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=we(i.placement),l=je(a),c=[Xt,Qt].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return Fe("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:He(t,Ut))}(s.padding,i),d=ke(o),u="y"===l?Vt:Xt,f="y"===l?Kt:Qt,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],m=r[l]-i.rects.reference[l],g=Pe(o),_=g?"y"===l?g.clientHeight||0:g.clientWidth||0:0,b=p/2-m/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,A=Me(v,w,y),E=l;i.modifiersData[n]=((e={})[E]=A,e.centerOffset=A-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Le(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Be(t){return t.split("-")[1]}var ze={top:"auto",right:"auto",bottom:"auto",left:"auto"};function Re(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=t.isFixed,u=r.x,f=void 0===u?0:u,p=r.y,m=void 0===p?0:p,g="function"==typeof h?h({x:f,y:m}):{x:f,y:m};f=g.x,m=g.y;var _=r.hasOwnProperty("x"),b=r.hasOwnProperty("y"),v=Xt,y=Vt,w=window;if(c){var A=Pe(i),E="clientHeight",T="clientWidth";A===ge(i)&&"static"!==Se(A=$e(i)).position&&"absolute"===a&&(E="scrollHeight",T="scrollWidth"),(s===Vt||(s===Xt||s===Qt)&&o===Jt)&&(y=Kt,m-=(d&&A===w&&w.visualViewport?w.visualViewport.height:A[E])-n.height,m*=l?1:-1),s!==Xt&&(s!==Vt&&s!==Kt||o!==Jt)||(v=Qt,f-=(d&&A===w&&w.visualViewport?w.visualViewport.width:A[T])-n.width,f*=l?1:-1)}var C,O=Object.assign({position:a},c&&ze),x=!0===h?function(t,e){var i=t.x,n=t.y,s=e.devicePixelRatio||1;return{x:Te(i*s)/s||0,y:Te(n*s)/s||0}}({x:f,y:m},ge(i)):{x:f,y:m};return f=x.x,m=x.y,l?Object.assign({},O,((C={})[y]=b?"0":"",C[v]=_?"0":"",C.transform=(w.devicePixelRatio||1)<=1?"translate("+f+"px, "+m+"px)":"translate3d("+f+"px, "+m+"px, 0)",C)):Object.assign({},O,((e={})[y]=b?m+"px":"",e[v]=_?f+"px":"",e.transform="",e))}const qe={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:we(e.placement),variation:Be(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,Re(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,Re(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var Ve={passive:!0};const Ke={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=ge(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach(function(t){t.addEventListener("scroll",i.update,Ve)}),a&&l.addEventListener("resize",i.update,Ve),function(){o&&c.forEach(function(t){t.removeEventListener("scroll",i.update,Ve)}),a&&l.removeEventListener("resize",i.update,Ve)}},data:{}};var Qe={left:"right",right:"left",bottom:"top",top:"bottom"};function Xe(t){return t.replace(/left|right|bottom|top/g,function(t){return Qe[t]})}var Ye={start:"end",end:"start"};function Ue(t){return t.replace(/start|end/g,function(t){return Ye[t]})}function Ge(t){var e=ge(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Je(t){return xe($e(t)).left+Ge(t).scrollLeft}function Ze(t){var e=Se(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function ti(t){return["html","body","#document"].indexOf(me(t))>=0?t.ownerDocument.body:be(t)&&Ze(t)?t:ti(Ie(t))}function ei(t,e){var i;void 0===e&&(e=[]);var n=ti(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=ge(n),r=s?[o].concat(o.visualViewport||[],Ze(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(ei(Ie(r)))}function ii(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function ni(t,e,i){return e===te?ii(function(t,e){var i=ge(t),n=$e(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=Oe();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+Je(t),y:l}}(t,i)):_e(e)?function(t,e){var i=xe(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):ii(function(t){var e,i=$e(t),n=Ge(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=Ae(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=Ae(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+Je(t),l=-n.scrollTop;return"rtl"===Se(s||i).direction&&(a+=Ae(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}($e(t)))}function si(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?we(s):null,r=s?Be(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case Vt:e={x:a,y:i.y-n.height};break;case Kt:e={x:a,y:i.y+i.height};break;case Qt:e={x:i.x+i.width,y:l};break;case Xt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?je(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case Gt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case Jt:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function oi(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.strategy,r=void 0===o?t.strategy:o,a=i.boundary,l=void 0===a?Zt:a,c=i.rootBoundary,h=void 0===c?te:c,d=i.elementContext,u=void 0===d?ee:d,f=i.altBoundary,p=void 0!==f&&f,m=i.padding,g=void 0===m?0:m,_=Fe("number"!=typeof g?g:He(g,Ut)),b=u===ee?ie:ee,v=t.rects.popper,y=t.elements[p?b:u],w=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=ei(Ie(t)),i=["absolute","fixed"].indexOf(Se(t).position)>=0&&be(t)?Pe(t):t;return _e(i)?e.filter(function(t){return _e(t)&&Le(t,i)&&"body"!==me(t)}):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce(function(e,i){var s=ni(t,i,n);return e.top=Ae(s.top,e.top),e.right=Ee(s.right,e.right),e.bottom=Ee(s.bottom,e.bottom),e.left=Ae(s.left,e.left),e},ni(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(_e(y)?y:y.contextElement||$e(t.elements.popper),l,h,r),A=xe(t.elements.reference),E=si({reference:A,element:v,placement:s}),T=ii(Object.assign({},v,E)),C=u===ee?T:A,O={top:w.top-C.top+_.top,bottom:C.bottom-w.bottom+_.bottom,left:w.left-C.left+_.left,right:C.right-w.right+_.right},x=t.modifiersData.offset;if(u===ee&&x){var k=x[s];Object.keys(O).forEach(function(t){var e=[Qt,Kt].indexOf(t)>=0?1:-1,i=[Vt,Kt].indexOf(t)>=0?"y":"x";O[t]+=k[i]*e})}return O}function ri(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?se:l,h=Be(n),d=h?a?ne:ne.filter(function(t){return Be(t)===h}):Ut,u=d.filter(function(t){return c.indexOf(t)>=0});0===u.length&&(u=d);var f=u.reduce(function(e,i){return e[i]=oi(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[we(i)],e},{});return Object.keys(f).sort(function(t,e){return f[t]-f[e]})}const ai={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,m=i.allowedAutoPlacements,g=e.options.placement,_=we(g),b=l||(_!==g&&p?function(t){if(we(t)===Yt)return[];var e=Xe(t);return[Ue(t),e,Ue(e)]}(g):[Xe(g)]),v=[g].concat(b).reduce(function(t,i){return t.concat(we(i)===Yt?ri(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:m}):i)},[]),y=e.rects.reference,w=e.rects.popper,A=new Map,E=!0,T=v[0],C=0;C=0,S=L?"width":"height",D=oi(e,{placement:O,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),$=L?k?Qt:Xt:k?Kt:Vt;y[S]>w[S]&&($=Xe($));var I=Xe($),N=[];if(o&&N.push(D[x]<=0),a&&N.push(D[$]<=0,D[I]<=0),N.every(function(t){return t})){T=O,E=!1;break}A.set(O,N)}if(E)for(var P=function(t){var e=v.find(function(e){var i=A.get(e);if(i)return i.slice(0,t).every(function(t){return t})});if(e)return T=e,"break"},j=p?3:1;j>0&&"break"!==P(j);j--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function li(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function ci(t){return[Vt,Qt,Kt,Xt].some(function(e){return t[e]>=0})}const hi={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=oi(e,{elementContext:"reference"}),a=oi(e,{altBoundary:!0}),l=li(r,n),c=li(a,s,o),h=ci(l),d=ci(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},di={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=se.reduce(function(t,i){return t[i]=function(t,e,i){var n=we(t),s=[Xt,Vt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[Xt,Qt].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t},{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},ui={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=si({reference:e.rects.reference,element:e.rects.popper,placement:e.placement})},data:{}},fi={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,m=void 0===p?0:p,g=oi(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=we(e.placement),b=Be(e.placement),v=!b,y=je(_),w="x"===y?"y":"x",A=e.modifiersData.popperOffsets,E=e.rects.reference,T=e.rects.popper,C="function"==typeof m?m(Object.assign({},e.rects,{placement:e.placement})):m,O="number"==typeof C?{mainAxis:C,altAxis:C}:Object.assign({mainAxis:0,altAxis:0},C),x=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,k={x:0,y:0};if(A){if(o){var L,S="y"===y?Vt:Xt,D="y"===y?Kt:Qt,$="y"===y?"height":"width",I=A[y],N=I+g[S],P=I-g[D],j=f?-T[$]/2:0,M=b===Gt?E[$]:T[$],F=b===Gt?-T[$]:-E[$],H=e.elements.arrow,W=f&&H?ke(H):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},z=B[S],R=B[D],q=Me(0,E[$],W[$]),V=v?E[$]/2-j-q-z-O.mainAxis:M-q-z-O.mainAxis,K=v?-E[$]/2+j+q+R+O.mainAxis:F+q+R+O.mainAxis,Q=e.elements.arrow&&Pe(e.elements.arrow),X=Q?"y"===y?Q.clientTop||0:Q.clientLeft||0:0,Y=null!=(L=null==x?void 0:x[y])?L:0,U=I+K-Y,G=Me(f?Ee(N,I+V-Y-X):N,I,f?Ae(P,U):P);A[y]=G,k[y]=G-I}if(a){var J,Z="x"===y?Vt:Xt,tt="x"===y?Kt:Qt,et=A[w],it="y"===w?"height":"width",nt=et+g[Z],st=et-g[tt],ot=-1!==[Vt,Xt].indexOf(_),rt=null!=(J=null==x?void 0:x[w])?J:0,at=ot?nt:et-E[it]-T[it]-rt+O.altAxis,lt=ot?et+E[it]+T[it]-rt-O.altAxis:st,ct=f&&ot?function(t,e,i){var n=Me(t,e,i);return n>i?i:n}(at,et,lt):Me(f?at:nt,et,f?lt:st);A[w]=ct,k[w]=ct-et}e.modifiersData[n]=k}},requiresIfExists:["offset"]};function pi(t,e,i){void 0===i&&(i=!1);var n,s,o=be(e),r=be(e)&&function(t){var e=t.getBoundingClientRect(),i=Te(e.width)/t.offsetWidth||1,n=Te(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=$e(e),l=xe(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==me(e)||Ze(a))&&(c=(n=e)!==ge(n)&&be(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:Ge(n)),be(e)?((h=xe(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=Je(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function mi(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach(function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}}),n.push(t)}return t.forEach(function(t){e.set(t.name,t)}),t.forEach(function(t){i.has(t.name)||s(t)}),n}var gi={placement:"bottom",modifiers:[],strategy:"absolute"};function _i(){for(var t=arguments.length,e=new Array(t),i=0;iNumber.parseInt(t,10)):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(H.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,..._(this._config.popperConfig,[void 0,t])}}_selectMenuItem({key:t,target:e}){const i=R.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter(t=>l(t));i.length&&v(i,e,t===xi,!i.includes(e)).focus()}static jQueryInterface(t){return this.each(function(){const e=Qi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}})}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=R.find(Mi);for(const i of e){const e=Qi.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Oi,xi].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(ji)?this:R.prev(this,ji)[0]||R.next(this,ji)[0]||R.findOne(ji,t.delegateTarget.parentNode),o=Qi.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}P.on(document,Ii,ji,Qi.dataApiKeydownHandler),P.on(document,Ii,Fi,Qi.dataApiKeydownHandler),P.on(document,$i,Qi.clearMenus),P.on(document,Ni,Qi.clearMenus),P.on(document,$i,ji,function(t){t.preventDefault(),Qi.getOrCreateInstance(this).toggle()}),g(Qi);const Xi="backdrop",Yi="show",Ui=`mousedown.bs.${Xi}`,Gi={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Ji={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class Zi extends W{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return Gi}static get DefaultType(){return Ji}static get NAME(){return Xi}show(t){if(!this._config.isVisible)return void _(t);this._append();const e=this._getElement();this._config.isAnimated&&u(e),e.classList.add(Yi),this._emulateAnimation(()=>{_(t)})}hide(t){this._config.isVisible?(this._getElement().classList.remove(Yi),this._emulateAnimation(()=>{this.dispose(),_(t)})):_(t)}dispose(){this._isAppended&&(P.off(this._element,Ui),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=a(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),P.on(t,Ui,()=>{_(this._config.clickCallback)}),this._isAppended=!0}_emulateAnimation(t){b(t,this._getElement(),this._config.isAnimated)}}const tn=".bs.focustrap",en=`focusin${tn}`,nn=`keydown.tab${tn}`,sn="backward",on={autofocus:!0,trapElement:null},rn={autofocus:"boolean",trapElement:"element"};class an extends W{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return on}static get DefaultType(){return rn}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),P.off(document,tn),P.on(document,en,t=>this._handleFocusin(t)),P.on(document,nn,t=>this._handleKeydown(t)),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,P.off(document,tn))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=R.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===sn?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?sn:"forward")}}const ln=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",cn=".sticky-top",hn="padding-right",dn="margin-right";class un{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,hn,e=>e+t),this._setElementAttributes(ln,hn,e=>e+t),this._setElementAttributes(cn,dn,e=>e-t)}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,hn),this._resetElementAttributes(ln,hn),this._resetElementAttributes(cn,dn)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)})}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&H.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,t=>{const i=H.getDataAttribute(t,e);null!==i?(H.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)})}_applyManipulationCallback(t,e){if(r(t))e(t);else for(const i of R.find(t,this._element))e(i)}}const fn=".bs.modal",pn=`hide${fn}`,mn=`hidePrevented${fn}`,gn=`hidden${fn}`,_n=`show${fn}`,bn=`shown${fn}`,vn=`resize${fn}`,yn=`click.dismiss${fn}`,wn=`mousedown.dismiss${fn}`,An=`keydown.dismiss${fn}`,En=`click${fn}.data-api`,Tn="modal-open",Cn="show",On="modal-static",xn={backdrop:!0,focus:!0,keyboard:!0},kn={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class Ln extends B{constructor(t,e){super(t,e),this._dialog=R.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new un,this._addEventListeners()}static get Default(){return xn}static get DefaultType(){return kn}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||P.trigger(this._element,_n,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(Tn),this._adjustDialog(),this._backdrop.show(()=>this._showElement(t)))}hide(){this._isShown&&!this._isTransitioning&&(P.trigger(this._element,pn).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(Cn),this._queueCallback(()=>this._hideModal(),this._element,this._isAnimated())))}dispose(){P.off(window,fn),P.off(this._dialog,fn),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new Zi({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new an({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=R.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),u(this._element),this._element.classList.add(Cn),this._queueCallback(()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,P.trigger(this._element,bn,{relatedTarget:t})},this._dialog,this._isAnimated())}_addEventListeners(){P.on(this._element,An,t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())}),P.on(window,vn,()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()}),P.on(this._element,wn,t=>{P.one(this._element,yn,e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())})})}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide(()=>{document.body.classList.remove(Tn),this._resetAdjustments(),this._scrollBar.reset(),P.trigger(this._element,gn)})}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(P.trigger(this._element,mn).defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(On)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(On),this._queueCallback(()=>{this._element.classList.remove(On),this._queueCallback(()=>{this._element.style.overflowY=e},this._dialog)},this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=m()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=m()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each(function(){const i=Ln.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}})}}P.on(document,En,'[data-bs-toggle="modal"]',function(t){const e=R.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),P.one(e,_n,t=>{t.defaultPrevented||P.one(e,gn,()=>{l(this)&&this.focus()})});const i=R.findOne(".modal.show");i&&Ln.getInstance(i).hide(),Ln.getOrCreateInstance(e).toggle(this)}),q(Ln),g(Ln);const Sn=".bs.offcanvas",Dn=".data-api",$n=`load${Sn}${Dn}`,In="show",Nn="showing",Pn="hiding",jn=".offcanvas.show",Mn=`show${Sn}`,Fn=`shown${Sn}`,Hn=`hide${Sn}`,Wn=`hidePrevented${Sn}`,Bn=`hidden${Sn}`,zn=`resize${Sn}`,Rn=`click${Sn}${Dn}`,qn=`keydown.dismiss${Sn}`,Vn={backdrop:!0,keyboard:!0,scroll:!1},Kn={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class Qn extends B{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return Vn}static get DefaultType(){return Kn}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||P.trigger(this._element,Mn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new un).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Nn),this._queueCallback(()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(In),this._element.classList.remove(Nn),P.trigger(this._element,Fn,{relatedTarget:t})},this._element,!0))}hide(){this._isShown&&(P.trigger(this._element,Hn).defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add(Pn),this._backdrop.hide(),this._queueCallback(()=>{this._element.classList.remove(In,Pn),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new un).reset(),P.trigger(this._element,Bn)},this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new Zi({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():P.trigger(this._element,Wn)}:null})}_initializeFocusTrap(){return new an({trapElement:this._element})}_addEventListeners(){P.on(this._element,qn,t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():P.trigger(this._element,Wn))})}static jQueryInterface(t){return this.each(function(){const e=Qn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}})}}P.on(document,Rn,'[data-bs-toggle="offcanvas"]',function(t){const e=R.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),c(this))return;P.one(e,Bn,()=>{l(this)&&this.focus()});const i=R.findOne(jn);i&&i!==e&&Qn.getInstance(i).hide(),Qn.getOrCreateInstance(e).toggle(this)}),P.on(window,$n,()=>{for(const t of R.find(jn))Qn.getOrCreateInstance(t).show()}),P.on(window,zn,()=>{for(const t of R.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&Qn.getOrCreateInstance(t).hide()}),q(Qn),g(Qn);const Xn={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],dd:[],div:[],dl:[],dt:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Yn=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Un=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Gn=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!Yn.has(i)||Boolean(Un.test(t.nodeValue)):e.filter(t=>t instanceof RegExp).some(t=>t.test(i))},Jn={allowList:Xn,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},Zn={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},ts={entry:"(string|element|function|null)",selector:"(string|element)"};class es extends W{constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Jn}static get DefaultType(){return Zn}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map(t=>this._resolvePossibleFunction(t)).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},ts)}_setContent(t,e,i){const n=R.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?r(e)?this._putElementInTemplate(a(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Gn(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return _(t,[void 0,this])}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const is=new Set(["sanitize","allowList","sanitizeFn"]),ns="fade",ss="show",os=".tooltip-inner",rs=".modal",as="hide.bs.modal",ls="hover",cs="focus",hs="click",ds={AUTO:"auto",TOP:"top",RIGHT:m()?"left":"right",BOTTOM:"bottom",LEFT:m()?"right":"left"},us={allowList:Xn,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},fs={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class ps extends B{constructor(t,e){if(void 0===Ai)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org/docs/v2/)");super(t,e),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return us}static get DefaultType(){return fs}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),P.off(this._element.closest(rs),as,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=P.trigger(this._element,this.constructor.eventName("show")),e=(h(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),P.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(ss),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))P.on(t,"mouseover",d);this._queueCallback(()=>{P.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1},this.tip,this._isAnimated())}hide(){if(this._isShown()&&!P.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(ss),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))P.off(t,"mouseover",d);this._activeTrigger[hs]=!1,this._activeTrigger[cs]=!1,this._activeTrigger[ls]=!1,this._isHovered=null,this._queueCallback(()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),P.trigger(this._element,this.constructor.eventName("hidden")))},this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(ns,ss),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(ns),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new es({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{[os]:this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(ns)}_isShown(){return this.tip&&this.tip.classList.contains(ss)}_createPopper(t){const e=_(this._config.placement,[this,t,this._element]),i=ds[e.toUpperCase()];return wi(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map(t=>Number.parseInt(t,10)):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return _(t,[this._element,this._element])}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,..._(this._config.popperConfig,[void 0,e])}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)P.on(this._element,this.constructor.eventName("click"),this._config.selector,t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger[hs]=!(e._isShown()&&e._activeTrigger[hs]),e.toggle()});else if("manual"!==e){const t=e===ls?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===ls?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");P.on(this._element,t,this._config.selector,t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?cs:ls]=!0,e._enter()}),P.on(this._element,i,this._config.selector,t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?cs:ls]=e._element.contains(t.relatedTarget),e._leave()})}this._hideModalHandler=()=>{this._element&&this.hide()},P.on(this._element.closest(rs),as,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout(()=>{this._isHovered&&this.show()},this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout(()=>{this._isHovered||this.hide()},this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=H.getDataAttributes(this._element);for(const t of Object.keys(e))is.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:a(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const[e,i]of Object.entries(this._config))this.constructor.Default[e]!==i&&(t[e]=i);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each(function(){const e=ps.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}})}}g(ps);const ms=".popover-header",gs=".popover-body",_s={...ps.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},bs={...ps.DefaultType,content:"(null|string|element|function)"};class vs extends ps{static get Default(){return _s}static get DefaultType(){return bs}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{[ms]:this._getTitle(),[gs]:this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each(function(){const e=vs.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}})}}g(vs);const ys=".bs.scrollspy",ws=`activate${ys}`,As=`click${ys}`,Es=`load${ys}.data-api`,Ts="active",Cs="[href]",Os=".nav-link",xs=`${Os}, .nav-item > ${Os}, .list-group-item`,ks={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},Ls={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class Ss extends B{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return ks}static get DefaultType(){return Ls}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=a(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map(t=>Number.parseFloat(t))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(P.off(this._config.target,As),P.on(this._config.target,As,Cs,t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}}))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver(t=>this._observerCallback(t),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=R.find(Cs,this._config.target);for(const e of t){if(!e.hash||c(e))continue;const t=R.findOne(decodeURI(e.hash),this._element);l(t)&&(this._targetLinks.set(decodeURI(e.hash),e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(Ts),this._activateParents(t),P.trigger(this._element,ws,{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))R.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(Ts);else for(const e of R.parents(t,".nav, .list-group"))for(const t of R.prev(e,xs))t.classList.add(Ts)}_clearActiveClass(t){t.classList.remove(Ts);const e=R.find(`${Cs}.${Ts}`,t);for(const t of e)t.classList.remove(Ts)}static jQueryInterface(t){return this.each(function(){const e=Ss.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}})}}P.on(window,Es,()=>{for(const t of R.find('[data-bs-spy="scroll"]'))Ss.getOrCreateInstance(t)}),g(Ss);const Ds=".bs.tab",$s=`hide${Ds}`,Is=`hidden${Ds}`,Ns=`show${Ds}`,Ps=`shown${Ds}`,js=`click${Ds}`,Ms=`keydown${Ds}`,Fs=`load${Ds}`,Hs="ArrowLeft",Ws="ArrowRight",Bs="ArrowUp",zs="ArrowDown",Rs="Home",qs="End",Vs="active",Ks="fade",Qs="show",Xs=".dropdown-toggle",Ys=`:not(${Xs})`,Us='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',Gs=`.nav-link${Ys}, .list-group-item${Ys}, [role="tab"]${Ys}, ${Us}`,Js=`.${Vs}[data-bs-toggle="tab"], .${Vs}[data-bs-toggle="pill"], .${Vs}[data-bs-toggle="list"]`;class Zs extends B{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),P.on(this._element,Ms,t=>this._keydown(t)))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?P.trigger(e,$s,{relatedTarget:t}):null;P.trigger(t,Ns,{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(Vs),this._activate(R.getElementFromSelector(t)),this._queueCallback(()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),P.trigger(t,Ps,{relatedTarget:e})):t.classList.add(Qs)},t,t.classList.contains(Ks)))}_deactivate(t,e){t&&(t.classList.remove(Vs),t.blur(),this._deactivate(R.getElementFromSelector(t)),this._queueCallback(()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),P.trigger(t,Is,{relatedTarget:e})):t.classList.remove(Qs)},t,t.classList.contains(Ks)))}_keydown(t){if(![Hs,Ws,Bs,zs,Rs,qs].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=this._getChildren().filter(t=>!c(t));let i;if([Rs,qs].includes(t.key))i=e[t.key===Rs?0:e.length-1];else{const n=[Ws,zs].includes(t.key);i=v(e,t.target,n,!0)}i&&(i.focus({preventScroll:!0}),Zs.getOrCreateInstance(i).show())}_getChildren(){return R.find(Gs,this._parent)}_getActiveElem(){return this._getChildren().find(t=>this._elemIsActive(t))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=R.getElementFromSelector(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=R.findOne(t,i);s&&s.classList.toggle(n,e)};n(Xs,Vs),n(".dropdown-menu",Qs),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(Vs)}_getInnerElement(t){return t.matches(Gs)?t:R.findOne(Gs,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each(function(){const e=Zs.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}})}}P.on(document,js,Us,function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),c(this)||Zs.getOrCreateInstance(this).show()}),P.on(window,Fs,()=>{for(const t of R.find(Js))Zs.getOrCreateInstance(t)}),g(Zs);const to=".bs.toast",eo=`mouseover${to}`,io=`mouseout${to}`,no=`focusin${to}`,so=`focusout${to}`,oo=`hide${to}`,ro=`hidden${to}`,ao=`show${to}`,lo=`shown${to}`,co="hide",ho="show",uo="showing",fo={animation:"boolean",autohide:"boolean",delay:"number"},po={animation:!0,autohide:!0,delay:5e3};class mo extends B{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return po}static get DefaultType(){return fo}static get NAME(){return"toast"}show(){P.trigger(this._element,ao).defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(co),u(this._element),this._element.classList.add(ho,uo),this._queueCallback(()=>{this._element.classList.remove(uo),P.trigger(this._element,lo),this._maybeScheduleHide()},this._element,this._config.animation))}hide(){this.isShown()&&(P.trigger(this._element,oo).defaultPrevented||(this._element.classList.add(uo),this._queueCallback(()=>{this._element.classList.add(co),this._element.classList.remove(uo,ho),P.trigger(this._element,ro)},this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(ho),super.dispose()}isShown(){return this._element.classList.contains(ho)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout(()=>{this.hide()},this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){P.on(this._element,eo,t=>this._onInteraction(t,!0)),P.on(this._element,io,t=>this._onInteraction(t,!1)),P.on(this._element,no,t=>this._onInteraction(t,!0)),P.on(this._element,so,t=>this._onInteraction(t,!1))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each(function(){const e=mo.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}})}}return q(mo),g(mo),{Alert:X,Button:U,Carousel:St,Collapse:qt,Dropdown:Qi,Modal:Ln,Offcanvas:Qn,Popover:vs,ScrollSpy:Ss,Tab:Zs,Toast:mo,Tooltip:ps}}); //# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/core/src/main/resources/org/apache/spark/ui/static/bootstrap.min.css b/core/src/main/resources/org/apache/spark/ui/static/bootstrap.min.css index 83a71b1f50721..1d8bac41b3b58 100644 --- a/core/src/main/resources/org/apache/spark/ui/static/bootstrap.min.css +++ b/core/src/main/resources/org/apache/spark/ui/static/bootstrap.min.css @@ -1,7 +1,6 @@ -/*! - * Bootstrap v4.6.2 (https://getbootstrap.com/) - * Copyright 2011-2022 The Bootstrap Authors - * Copyright 2011-2022 Twitter, Inc. +@charset "UTF-8";/*! + * Bootstrap v5.3.8 (https://getbootstrap.com/) + * Copyright 2011-2025 The Bootstrap Authors * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:.875em;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#28a745}.valid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem)!important;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated select.form-control:valid,select.form-control.is-valid{padding-right:3rem!important;background-position:right 1.5rem center}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem)!important;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem)!important;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated select.form-control:invalid,select.form-control.is-invalid{padding-right:3rem!important;background-position:right 1.5rem center}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem)!important;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.width{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.width{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label,.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label::after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label,.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label::after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;z-index:1;display:block;min-height:1.5rem;padding-left:1.5rem;-webkit-print-color-adjust:exact;color-adjust:exact;print-color-adjust:exact}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before,.custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:1px solid #adb5bd}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;overflow:hidden;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;overflow:hidden;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;background-color:transparent;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{background:0 0;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item,.nav-fill>.nav-link{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:50%/100% 100% no-repeat}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;z-index:2;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:1s linear infinite progress-bar-stripes;animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{-ms-flex-preferred-size:350px;flex-basis:350px;max-width:350px;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);height:-webkit-min-content;height:-moz-min-content;height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem);height:-webkit-min-content;height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:50%/100% 100% no-repeat}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;border:.25em solid currentcolor;border-right-color:transparent;border-radius:50%;-webkit-animation:.75s linear infinite spinner-border;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;background-color:currentcolor;border-radius:50%;opacity:0;-webkit-animation:.75s linear infinite spinner-grow;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{-webkit-animation-duration:1.5s;animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;word-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}} + */:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-primary-text-emphasis:#052c65;--bs-secondary-text-emphasis:#2b2f32;--bs-success-text-emphasis:#0a3622;--bs-info-text-emphasis:#055160;--bs-warning-text-emphasis:#664d03;--bs-danger-text-emphasis:#58151c;--bs-light-text-emphasis:#495057;--bs-dark-text-emphasis:#495057;--bs-primary-bg-subtle:#cfe2ff;--bs-secondary-bg-subtle:#e2e3e5;--bs-success-bg-subtle:#d1e7dd;--bs-info-bg-subtle:#cff4fc;--bs-warning-bg-subtle:#fff3cd;--bs-danger-bg-subtle:#f8d7da;--bs-light-bg-subtle:#fcfcfd;--bs-dark-bg-subtle:#ced4da;--bs-primary-border-subtle:#9ec5fe;--bs-secondary-border-subtle:#c4c8cb;--bs-success-border-subtle:#a3cfbb;--bs-info-border-subtle:#9eeaf9;--bs-warning-border-subtle:#ffe69c;--bs-danger-border-subtle:#f1aeb5;--bs-light-border-subtle:#e9ecef;--bs-dark-border-subtle:#adb5bd;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-color-rgb:33,37,41;--bs-body-bg:#fff;--bs-body-bg-rgb:255,255,255;--bs-emphasis-color:#000;--bs-emphasis-color-rgb:0,0,0;--bs-secondary-color:rgba(33, 37, 41, 0.75);--bs-secondary-color-rgb:33,37,41;--bs-secondary-bg:#e9ecef;--bs-secondary-bg-rgb:233,236,239;--bs-tertiary-color:rgba(33, 37, 41, 0.5);--bs-tertiary-color-rgb:33,37,41;--bs-tertiary-bg:#f8f9fa;--bs-tertiary-bg-rgb:248,249,250;--bs-heading-color:inherit;--bs-link-color:#0d6efd;--bs-link-color-rgb:13,110,253;--bs-link-decoration:underline;--bs-link-hover-color:#0a58ca;--bs-link-hover-color-rgb:10,88,202;--bs-code-color:#d63384;--bs-highlight-color:#212529;--bs-highlight-bg:#fff3cd;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0, 0, 0, 0.175);--bs-border-radius:0.375rem;--bs-border-radius-sm:0.25rem;--bs-border-radius-lg:0.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-xxl:2rem;--bs-border-radius-2xl:var(--bs-border-radius-xxl);--bs-border-radius-pill:50rem;--bs-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-box-shadow-sm:0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-box-shadow-lg:0 1rem 3rem rgba(0, 0, 0, 0.175);--bs-box-shadow-inset:inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-focus-ring-width:0.25rem;--bs-focus-ring-opacity:0.25;--bs-focus-ring-color:rgba(13, 110, 253, 0.25);--bs-form-valid-color:#198754;--bs-form-valid-border-color:#198754;--bs-form-invalid-color:#dc3545;--bs-form-invalid-border-color:#dc3545}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color:#dee2e6;--bs-body-color-rgb:222,226,230;--bs-body-bg:#212529;--bs-body-bg-rgb:33,37,41;--bs-emphasis-color:#fff;--bs-emphasis-color-rgb:255,255,255;--bs-secondary-color:rgba(222, 226, 230, 0.75);--bs-secondary-color-rgb:222,226,230;--bs-secondary-bg:#343a40;--bs-secondary-bg-rgb:52,58,64;--bs-tertiary-color:rgba(222, 226, 230, 0.5);--bs-tertiary-color-rgb:222,226,230;--bs-tertiary-bg:#2b3035;--bs-tertiary-bg-rgb:43,48,53;--bs-primary-text-emphasis:#6ea8fe;--bs-secondary-text-emphasis:#a7acb1;--bs-success-text-emphasis:#75b798;--bs-info-text-emphasis:#6edff6;--bs-warning-text-emphasis:#ffda6a;--bs-danger-text-emphasis:#ea868f;--bs-light-text-emphasis:#f8f9fa;--bs-dark-text-emphasis:#dee2e6;--bs-primary-bg-subtle:#031633;--bs-secondary-bg-subtle:#161719;--bs-success-bg-subtle:#051b11;--bs-info-bg-subtle:#032830;--bs-warning-bg-subtle:#332701;--bs-danger-bg-subtle:#2c0b0e;--bs-light-bg-subtle:#343a40;--bs-dark-bg-subtle:#1a1d20;--bs-primary-border-subtle:#084298;--bs-secondary-border-subtle:#41464b;--bs-success-border-subtle:#0f5132;--bs-info-border-subtle:#087990;--bs-warning-border-subtle:#997404;--bs-danger-border-subtle:#842029;--bs-light-border-subtle:#495057;--bs-dark-border-subtle:#343a40;--bs-heading-color:inherit;--bs-link-color:#6ea8fe;--bs-link-hover-color:#8bb9fe;--bs-link-color-rgb:110,168,254;--bs-link-hover-color-rgb:139,185,254;--bs-code-color:#e685b5;--bs-highlight-color:#dee2e6;--bs-highlight-bg:#664d03;--bs-border-color:#495057;--bs-border-color-translucent:rgba(255, 255, 255, 0.15);--bs-form-valid-color:#75b798;--bs-form-valid-border-color:#75b798;--bs-form-invalid-color:#ea868f;--bs-form-invalid-border-color:#ea868f}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;border:0;border-top:var(--bs-border-width) solid;opacity:.25}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color)}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.1875em;color:var(--bs-highlight-color);background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,1));text-decoration:underline}a:hover{--bs-link-color-rgb:var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:var(--bs-code-color);word-wrap:break-word}a>code{color:inherit}kbd{padding:.1875rem .375rem;font-size:.875em;color:var(--bs-body-bg);background-color:var(--bs-body-color);border-radius:.25rem}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-secondary-color);text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;line-height:inherit;font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button{cursor:pointer;filter:grayscale(1)}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-weight:300;line-height:1.2;font-size:calc(1.625rem + 4.5vw)}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-weight:300;line-height:1.2;font-size:calc(1.575rem + 3.9vw)}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-weight:300;line-height:1.2;font-size:calc(1.525rem + 3.3vw)}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-weight:300;line-height:1.2;font-size:calc(1.475rem + 2.7vw)}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-weight:300;line-height:1.2;font-size:calc(1.425rem + 2.1vw)}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-weight:300;line-height:1.2;font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:var(--bs-body-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:var(--bs-secondary-color)}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{--bs-gutter-x:1.5rem;--bs-gutter-y:0;width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}:root{--bs-breakpoint-xs:0;--bs-breakpoint-sm:576px;--bs-breakpoint-md:768px;--bs-breakpoint-lg:992px;--bs-breakpoint-xl:1200px;--bs-breakpoint-xxl:1400px}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(-1 * var(--bs-gutter-y));margin-right:calc(-.5 * var(--bs-gutter-x));margin-left:calc(-.5 * var(--bs-gutter-x))}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.66666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm{flex:1 0 0}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.66666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md{flex:1 0 0}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.66666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg{flex:1 0 0}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.66666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl{flex:1 0 0}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.66666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl{flex:1 0 0}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.66666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-color-type:initial;--bs-table-bg-type:initial;--bs-table-color-state:initial;--bs-table-bg-state:initial;--bs-table-color:var(--bs-emphasis-color);--bs-table-bg:var(--bs-body-bg);--bs-table-border-color:var(--bs-border-color);--bs-table-accent-bg:transparent;--bs-table-striped-color:var(--bs-emphasis-color);--bs-table-striped-bg:rgba(var(--bs-emphasis-color-rgb), 0.05);--bs-table-active-color:var(--bs-emphasis-color);--bs-table-active-bg:rgba(var(--bs-emphasis-color-rgb), 0.1);--bs-table-hover-color:var(--bs-emphasis-color);--bs-table-hover-bg:rgba(var(--bs-emphasis-color-rgb), 0.075);width:100%;margin-bottom:1rem;vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*{padding:.5rem .5rem;color:var(--bs-table-color-state,var(--bs-table-color-type,var(--bs-table-color)));background-color:var(--bs-table-bg);border-bottom-width:var(--bs-border-width);box-shadow:inset 0 0 0 9999px var(--bs-table-bg-state,var(--bs-table-bg-type,var(--bs-table-accent-bg)))}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-group-divider{border-top:calc(var(--bs-border-width) * 2) solid currentcolor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:var(--bs-border-width) 0}.table-bordered>:not(caption)>*>*{border-width:0 var(--bs-border-width)}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-striped-columns>:not(caption)>tr>:nth-child(2n){--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-active{--bs-table-color-state:var(--bs-table-active-color);--bs-table-bg-state:var(--bs-table-active-bg)}.table-hover>tbody>tr:hover>*{--bs-table-color-state:var(--bs-table-hover-color);--bs-table-bg-state:var(--bs-table-hover-bg)}.table-primary{--bs-table-color:#000;--bs-table-bg:#cfe2ff;--bs-table-border-color:#a6b5cc;--bs-table-striped-bg:#c5d7f2;--bs-table-striped-color:#000;--bs-table-active-bg:#bacbe6;--bs-table-active-color:#000;--bs-table-hover-bg:#bfd1ec;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-secondary{--bs-table-color:#000;--bs-table-bg:#e2e3e5;--bs-table-border-color:#b5b6b7;--bs-table-striped-bg:#d7d8da;--bs-table-striped-color:#000;--bs-table-active-bg:#cbccce;--bs-table-active-color:#000;--bs-table-hover-bg:#d1d2d4;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-success{--bs-table-color:#000;--bs-table-bg:#d1e7dd;--bs-table-border-color:#a7b9b1;--bs-table-striped-bg:#c7dbd2;--bs-table-striped-color:#000;--bs-table-active-bg:#bcd0c7;--bs-table-active-color:#000;--bs-table-hover-bg:#c1d6cc;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-info{--bs-table-color:#000;--bs-table-bg:#cff4fc;--bs-table-border-color:#a6c3ca;--bs-table-striped-bg:#c5e8ef;--bs-table-striped-color:#000;--bs-table-active-bg:#badce3;--bs-table-active-color:#000;--bs-table-hover-bg:#bfe2e9;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-warning{--bs-table-color:#000;--bs-table-bg:#fff3cd;--bs-table-border-color:#ccc2a4;--bs-table-striped-bg:#f2e7c3;--bs-table-striped-color:#000;--bs-table-active-bg:#e6dbb9;--bs-table-active-color:#000;--bs-table-hover-bg:#ece1be;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-danger{--bs-table-color:#000;--bs-table-bg:#f8d7da;--bs-table-border-color:#c6acae;--bs-table-striped-bg:#eccccf;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc2c4;--bs-table-active-color:#000;--bs-table-hover-bg:#e5c7ca;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color:#000;--bs-table-bg:#f8f9fa;--bs-table-border-color:#c6c7c8;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color:#fff;--bs-table-bg:#212529;--bs-table-border-color:#4d5154;--bs-table-striped-bg:#2c3034;--bs-table-striped-color:#fff;--bs-table-active-bg:#373b3e;--bs-table-active-color:#fff;--bs-table-hover-bg:#323539;--bs-table-hover-color:#fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + var(--bs-border-width));padding-bottom:calc(.375rem + var(--bs-border-width));margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + var(--bs-border-width));padding-bottom:calc(.5rem + var(--bs-border-width));font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + var(--bs-border-width));padding-bottom:calc(.25rem + var(--bs-border-width));font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:var(--bs-secondary-color)}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-control::-webkit-date-and-time-value{min-width:85px;height:1.5em;margin:0}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:var(--bs-secondary-color);opacity:1}.form-control:disabled{background-color:var(--bs-secondary-bg);opacity:1}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:var(--bs-secondary-bg)}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--bs-secondary-bg)}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:var(--bs-body-color);background-color:transparent;border:solid transparent;border-width:var(--bs-border-width) 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2));padding:.25rem .5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2));padding:.5rem 1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2))}textarea.form-control-sm{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}textarea.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2))}.form-control-color{width:3rem;height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2));padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0!important;border-radius:var(--bs-border-radius)}.form-control-color::-webkit-color-swatch{border:0!important;border-radius:var(--bs-border-radius)}.form-control-color.form-control-sm{height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2))}.form-select{--bs-form-select-bg-img:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon,none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:var(--bs-secondary-bg)}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 var(--bs-body-color)}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}[data-bs-theme=dark] .form-select{--bs-form-select-bg-img:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-reverse{padding-right:1.5em;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:-1.5em;margin-left:0}.form-check-input{--bs-form-check-bg:var(--bs-body-bg);flex-shrink:0;width:1em;height:1em;margin-top:.25em;vertical-align:top;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-form-check-bg);background-image:var(--bs-form-check-bg-image);background-repeat:no-repeat;background-position:center;background-size:contain;border:var(--bs-border-width) solid var(--bs-border-color);-webkit-print-color-adjust:exact;color-adjust:exact;print-color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{cursor:default;opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");width:2em;margin-left:-2.5em;background-image:var(--bs-form-switch-bg);background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5em;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5em;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{pointer-events:none;filter:none;opacity:.65}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.form-range{width:100%;height:1.5rem;padding:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;-webkit-appearance:none;appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-secondary-bg);border-color:transparent;border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;-moz-appearance:none;appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-secondary-bg);border-color:transparent;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:var(--bs-secondary-color)}.form-range:disabled::-moz-range-thumb{background-color:var(--bs-secondary-color)}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + calc(var(--bs-border-width) * 2));min-height:calc(3.5rem + calc(var(--bs-border-width) * 2));line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;z-index:2;max-width:100%;height:100%;padding:1rem .75rem;overflow:hidden;color:rgba(var(--bs-body-color-rgb),.65);text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:var(--bs-border-width) solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control-plaintext::placeholder,.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown),.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control-plaintext:-webkit-autofill,.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem;padding-left:.75rem}.form-floating>.form-control-plaintext~label,.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>textarea:focus~label::after,.form-floating>textarea:not(:placeholder-shown)~label::after{position:absolute;inset:1rem 0.375rem;z-index:-1;height:1.5em;content:"";background-color:var(--bs-body-bg);border-radius:var(--bs-border-radius)}.form-floating>textarea:disabled~label::after{background-color:var(--bs-secondary-bg)}.form-floating>.form-control-plaintext~label{border-width:var(--bs-border-width) 0}.form-floating>.form-control:disabled~label,.form-floating>:disabled~label{color:#6c757d}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-floating,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-floating:focus-within,.input-group>.form-select:focus{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);text-align:center;white-space:nowrap;background-color:var(--bs-tertiary-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius)}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{padding:.25rem .5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select,.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select,.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:calc(-1 * var(--bs-border-width));border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--bs-form-valid-color)}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-success);border-radius:var(--bs-border-radius)}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:var(--bs-form-valid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:var(--bs-form-valid-border-color)}.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"]{--bs-form-select-bg-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-control-color.is-valid,.was-validated .form-control-color:valid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:var(--bs-form-valid-border-color)}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:var(--bs-form-valid-color)}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:var(--bs-form-valid-color)}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-valid,.input-group>.form-floating:not(:focus-within).is-valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-control:not(:focus):valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.was-validated .input-group>.form-select:not(:focus):valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--bs-form-invalid-color)}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-danger);border-radius:var(--bs-border-radius)}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:var(--bs-form-invalid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:var(--bs-form-invalid-border-color)}.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"]{--bs-form-select-bg-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-control-color.is-invalid,.was-validated .form-control-color:invalid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:var(--bs-form-invalid-border-color)}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:var(--bs-form-invalid-color)}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:var(--bs-form-invalid-color)}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-invalid,.input-group>.form-floating:not(:focus-within).is-invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-control:not(:focus):invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.was-validated .input-group>.form-select:not(:focus):invalid{z-index:4}.btn{--bs-btn-padding-x:0.75rem;--bs-btn-padding-y:0.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-color:var(--bs-body-color);--bs-btn-bg:transparent;--bs-btn-border-width:var(--bs-border-width);--bs-btn-border-color:transparent;--bs-btn-border-radius:var(--bs-border-radius);--bs-btn-hover-border-color:transparent;--bs-btn-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.15),0 1px 1px rgba(0, 0, 0, 0.075);--bs-btn-disabled-opacity:0.65;--bs-btn-focus-box-shadow:0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,.btn.active,.btn.show,.btn:first-child:active,:not(.btn-check)+.btn:active{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}.btn-check:checked+.btn:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible,.btn:first-child:active:focus-visible,:not(.btn-check)+.btn:active:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked:focus-visible+.btn{box-shadow:var(--bs-btn-focus-box-shadow)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity)}.btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0b5ed7;--bs-btn-hover-border-color:#0a58ca;--bs-btn-focus-shadow-rgb:49,132,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0a58ca;--bs-btn-active-border-color:#0a53be;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#0d6efd;--bs-btn-disabled-border-color:#0d6efd}.btn-secondary{--bs-btn-color:#fff;--bs-btn-bg:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#5c636a;--bs-btn-hover-border-color:#565e64;--bs-btn-focus-shadow-rgb:130,138,145;--bs-btn-active-color:#fff;--bs-btn-active-bg:#565e64;--bs-btn-active-border-color:#51585e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#6c757d;--bs-btn-disabled-border-color:#6c757d}.btn-success{--bs-btn-color:#fff;--bs-btn-bg:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#157347;--bs-btn-hover-border-color:#146c43;--bs-btn-focus-shadow-rgb:60,153,110;--bs-btn-active-color:#fff;--bs-btn-active-bg:#146c43;--bs-btn-active-border-color:#13653f;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#198754;--bs-btn-disabled-border-color:#198754}.btn-info{--bs-btn-color:#000;--bs-btn-bg:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#31d2f2;--bs-btn-hover-border-color:#25cff2;--bs-btn-focus-shadow-rgb:11,172,204;--bs-btn-active-color:#000;--bs-btn-active-bg:#3dd5f3;--bs-btn-active-border-color:#25cff2;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#0dcaf0;--bs-btn-disabled-border-color:#0dcaf0}.btn-warning{--bs-btn-color:#000;--bs-btn-bg:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffca2c;--bs-btn-hover-border-color:#ffc720;--bs-btn-focus-shadow-rgb:217,164,6;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffcd39;--bs-btn-active-border-color:#ffc720;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#ffc107;--bs-btn-disabled-border-color:#ffc107}.btn-danger{--bs-btn-color:#fff;--bs-btn-bg:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#bb2d3b;--bs-btn-hover-border-color:#b02a37;--bs-btn-focus-shadow-rgb:225,83,97;--bs-btn-active-color:#fff;--bs-btn-active-bg:#b02a37;--bs-btn-active-border-color:#a52834;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#dc3545;--bs-btn-disabled-border-color:#dc3545}.btn-light{--bs-btn-color:#000;--bs-btn-bg:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#d3d4d5;--bs-btn-hover-border-color:#c6c7c8;--bs-btn-focus-shadow-rgb:211,212,213;--bs-btn-active-color:#000;--bs-btn-active-bg:#c6c7c8;--bs-btn-active-border-color:#babbbc;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#f8f9fa;--bs-btn-disabled-border-color:#f8f9fa}.btn-dark{--bs-btn-color:#fff;--bs-btn-bg:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#424649;--bs-btn-hover-border-color:#373b3e;--bs-btn-focus-shadow-rgb:66,70,73;--bs-btn-active-color:#fff;--bs-btn-active-bg:#4d5154;--bs-btn-active-border-color:#373b3e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#212529;--bs-btn-disabled-border-color:#212529}.btn-outline-primary{--bs-btn-color:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0d6efd;--bs-btn-hover-border-color:#0d6efd;--bs-btn-focus-shadow-rgb:13,110,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0d6efd;--bs-btn-active-border-color:#0d6efd;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#0d6efd;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0d6efd;--bs-gradient:none}.btn-outline-secondary{--bs-btn-color:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#6c757d;--bs-btn-hover-border-color:#6c757d;--bs-btn-focus-shadow-rgb:108,117,125;--bs-btn-active-color:#fff;--bs-btn-active-bg:#6c757d;--bs-btn-active-border-color:#6c757d;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#6c757d;--bs-gradient:none}.btn-outline-success{--bs-btn-color:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#198754;--bs-btn-hover-border-color:#198754;--bs-btn-focus-shadow-rgb:25,135,84;--bs-btn-active-color:#fff;--bs-btn-active-bg:#198754;--bs-btn-active-border-color:#198754;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#198754;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#198754;--bs-gradient:none}.btn-outline-info{--bs-btn-color:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#0dcaf0;--bs-btn-hover-border-color:#0dcaf0;--bs-btn-focus-shadow-rgb:13,202,240;--bs-btn-active-color:#000;--bs-btn-active-bg:#0dcaf0;--bs-btn-active-border-color:#0dcaf0;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#0dcaf0;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0dcaf0;--bs-gradient:none}.btn-outline-warning{--bs-btn-color:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffc107;--bs-btn-hover-border-color:#ffc107;--bs-btn-focus-shadow-rgb:255,193,7;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffc107;--bs-btn-active-border-color:#ffc107;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#ffc107;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#ffc107;--bs-gradient:none}.btn-outline-danger{--bs-btn-color:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#dc3545;--bs-btn-hover-border-color:#dc3545;--bs-btn-focus-shadow-rgb:220,53,69;--bs-btn-active-color:#fff;--bs-btn-active-bg:#dc3545;--bs-btn-active-border-color:#dc3545;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#dc3545;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#dc3545;--bs-gradient:none}.btn-outline-light{--bs-btn-color:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#f8f9fa;--bs-btn-hover-border-color:#f8f9fa;--bs-btn-focus-shadow-rgb:248,249,250;--bs-btn-active-color:#000;--bs-btn-active-bg:#f8f9fa;--bs-btn-active-border-color:#f8f9fa;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#f8f9fa;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#f8f9fa;--bs-gradient:none}.btn-outline-dark{--bs-btn-color:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#212529;--bs-btn-hover-border-color:#212529;--bs-btn-focus-shadow-rgb:33,37,41;--bs-btn-active-color:#fff;--bs-btn-active-bg:#212529;--bs-btn-active-border-color:#212529;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#212529;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#212529;--bs-gradient:none}.btn-link{--bs-btn-font-weight:400;--bs-btn-color:var(--bs-link-color);--bs-btn-bg:transparent;--bs-btn-border-color:transparent;--bs-btn-hover-color:var(--bs-link-hover-color);--bs-btn-hover-border-color:transparent;--bs-btn-active-color:var(--bs-link-hover-color);--bs-btn-active-border-color:transparent;--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-border-color:transparent;--bs-btn-box-shadow:0 0 0 #000;--bs-btn-focus-shadow-rgb:49,132,253;text-decoration:underline}.btn-link:focus-visible{color:var(--bs-btn-color)}.btn-link:hover{color:var(--bs-btn-hover-color)}.btn-group-lg>.btn,.btn-lg{--bs-btn-padding-y:0.5rem;--bs-btn-padding-x:1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius:var(--bs-border-radius-lg)}.btn-group-sm>.btn,.btn-sm{--bs-btn-padding-y:0.25rem;--bs-btn-padding-x:0.5rem;--bs-btn-font-size:0.875rem;--bs-btn-border-radius:var(--bs-border-radius-sm)}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropdown,.dropdown-center,.dropend,.dropstart,.dropup,.dropup-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{--bs-dropdown-zindex:1000;--bs-dropdown-min-width:10rem;--bs-dropdown-padding-x:0;--bs-dropdown-padding-y:0.5rem;--bs-dropdown-spacer:0.125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color:var(--bs-body-color);--bs-dropdown-bg:var(--bs-body-bg);--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-border-radius:var(--bs-border-radius);--bs-dropdown-border-width:var(--bs-border-width);--bs-dropdown-inner-border-radius:calc(var(--bs-border-radius) - var(--bs-border-width));--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-divider-margin-y:0.5rem;--bs-dropdown-box-shadow:var(--bs-box-shadow);--bs-dropdown-link-color:var(--bs-body-color);--bs-dropdown-link-hover-color:var(--bs-body-color);--bs-dropdown-link-hover-bg:var(--bs-tertiary-bg);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:var(--bs-tertiary-color);--bs-dropdown-item-padding-x:1rem;--bs-dropdown-item-padding-y:0.25rem;--bs-dropdown-header-color:#6c757d;--bs-dropdown-header-padding-x:1rem;--bs-dropdown-header-padding-y:0.5rem;position:absolute;z-index:var(--bs-dropdown-zindex);display:none;min-width:var(--bs-dropdown-min-width);padding:var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);margin:0;font-size:var(--bs-dropdown-font-size);color:var(--bs-dropdown-color);text-align:left;list-style:none;background-color:var(--bs-dropdown-bg);background-clip:padding-box;border:var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color);border-radius:var(--bs-dropdown-border-radius)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--bs-dropdown-spacer)}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--bs-dropdown-spacer)}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--bs-dropdown-spacer)}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--bs-dropdown-spacer)}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:var(--bs-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0;border-radius:var(--bs-dropdown-item-border-radius,0)}.dropdown-item:focus,.dropdown-item:hover{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color:#dee2e6;--bs-dropdown-bg:#343a40;--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color:#dee2e6;--bs-dropdown-link-hover-color:#fff;--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-link-hover-bg:rgba(255, 255, 255, 0.15);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:#adb5bd;--bs-dropdown-header-color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:var(--bs-border-radius)}.btn-group>.btn-group:not(:first-child),.btn-group>:not(.btn-check:first-child)+.btn{margin-left:calc(-1 * var(--bs-border-width))}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:calc(-1 * var(--bs-border-width))}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:nth-child(n+3),.btn-group-vertical>:not(.btn-check)+.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--bs-nav-link-padding-x:1rem;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-link-color);--bs-nav-link-hover-color:var(--bs-link-hover-color);--bs-nav-link-disabled-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;background:0 0;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.nav-link.disabled,.nav-link:disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width:var(--bs-border-width);--bs-nav-tabs-border-color:var(--bs-border-color);--bs-nav-tabs-border-radius:var(--bs-border-radius);--bs-nav-tabs-link-hover-border-color:var(--bs-secondary-bg) var(--bs-secondary-bg) var(--bs-border-color);--bs-nav-tabs-link-active-color:var(--bs-emphasis-color);--bs-nav-tabs-link-active-bg:var(--bs-body-bg);--bs-nav-tabs-link-active-border-color:var(--bs-border-color) var(--bs-border-color) var(--bs-body-bg);border-bottom:var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1 * var(--bs-nav-tabs-border-width));border:var(--bs-nav-tabs-border-width) solid transparent;border-top-left-radius:var(--bs-nav-tabs-border-radius);border-top-right-radius:var(--bs-nav-tabs-border-radius)}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1 * var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius:var(--bs-border-radius);--bs-nav-pills-link-active-color:#fff;--bs-nav-pills-link-active-bg:#0d6efd}.nav-pills .nav-link{border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg)}.nav-underline{--bs-nav-underline-gap:1rem;--bs-nav-underline-border-width:0.125rem;--bs-nav-underline-link-active-color:var(--bs-emphasis-color);gap:var(--bs-nav-underline-gap)}.nav-underline .nav-link{padding-right:0;padding-left:0;border-bottom:var(--bs-nav-underline-border-width) solid transparent}.nav-underline .nav-link:focus,.nav-underline .nav-link:hover{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .show>.nav-link{font-weight:700;color:var(--bs-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-grow:1;flex-basis:0;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x:0;--bs-navbar-padding-y:0.5rem;--bs-navbar-color:rgba(var(--bs-emphasis-color-rgb), 0.65);--bs-navbar-hover-color:rgba(var(--bs-emphasis-color-rgb), 0.8);--bs-navbar-disabled-color:rgba(var(--bs-emphasis-color-rgb), 0.3);--bs-navbar-active-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-padding-y:0.3125rem;--bs-navbar-brand-margin-end:1rem;--bs-navbar-brand-font-size:1.25rem;--bs-navbar-brand-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-hover-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-nav-link-padding-x:0.5rem;--bs-navbar-toggler-padding-y:0.25rem;--bs-navbar-toggler-padding-x:0.75rem;--bs-navbar-toggler-font-size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2833, 37, 41, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color:rgba(var(--bs-emphasis-color-rgb), 0.15);--bs-navbar-toggler-border-radius:var(--bs-border-radius);--bs-navbar-toggler-focus-width:0.25rem;--bs-navbar-toggler-transition:box-shadow 0.15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x:0;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-navbar-color);--bs-nav-link-hover-color:var(--bs-navbar-hover-color);--bs-nav-link-disabled-color:var(--bs-navbar-disabled-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text a:focus,.navbar-text a:hover{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-grow:1;flex-basis:100%;align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:transparent;border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media (min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}.navbar-dark,.navbar[data-bs-theme=dark]{--bs-navbar-color:rgba(255, 255, 255, 0.55);--bs-navbar-hover-color:rgba(255, 255, 255, 0.75);--bs-navbar-disabled-color:rgba(255, 255, 255, 0.25);--bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-toggler-border-color:rgba(255, 255, 255, 0.1);--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}[data-bs-theme=dark] .navbar-toggler-icon{--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y:1rem;--bs-card-spacer-x:1rem;--bs-card-title-spacer-y:0.5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width:var(--bs-border-width);--bs-card-border-color:var(--bs-border-color-translucent);--bs-card-border-radius:var(--bs-border-radius);--bs-card-box-shadow: ;--bs-card-inner-border-radius:calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-card-cap-padding-y:0.5rem;--bs-card-cap-padding-x:1rem;--bs-card-cap-bg:rgba(var(--bs-body-color-rgb), 0.03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg:var(--bs-body-bg);--bs-card-img-overlay-padding:1rem;--bs-card-group-margin:0.75rem;position:relative;display:flex;flex-direction:column;min-width:0;height:var(--bs-card-height);color:var(--bs-body-color);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x);color:var(--bs-card-color)}.card-title{margin-bottom:var(--bs-card-title-spacer-y);color:var(--bs-card-title-color)}.card-subtitle{margin-top:calc(-.5 * var(--bs-card-title-spacer-y));margin-bottom:0;color:var(--bs-card-subtitle-color)}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:var(--bs-card-spacer-x)}.card-header{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);margin-bottom:0;color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.card-footer{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-top:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-bottom:calc(-1 * var(--bs-card-cap-padding-y));margin-left:calc(-.5 * var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-left:calc(-.5 * var(--bs-card-cap-padding-x))}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:var(--bs-card-img-overlay-padding);border-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--bs-card-group-margin)}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child)>.card-header,.card-group>.card:not(:last-child)>.card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child)>.card-footer,.card-group>.card:not(:last-child)>.card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child)>.card-header,.card-group>.card:not(:first-child)>.card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child)>.card-footer,.card-group>.card:not(:first-child)>.card-img-bottom{border-bottom-left-radius:0}}.accordion{--bs-accordion-color:var(--bs-body-color);--bs-accordion-bg:var(--bs-body-bg);--bs-accordion-transition:color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out,border-radius 0.15s ease;--bs-accordion-border-color:var(--bs-border-color);--bs-accordion-border-width:var(--bs-border-width);--bs-accordion-border-radius:var(--bs-border-radius);--bs-accordion-inner-border-radius:calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-accordion-btn-padding-x:1.25rem;--bs-accordion-btn-padding-y:1rem;--bs-accordion-btn-color:var(--bs-body-color);--bs-accordion-btn-bg:var(--bs-accordion-bg);--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23212529' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width:1.25rem;--bs-accordion-btn-icon-transform:rotate(-180deg);--bs-accordion-btn-icon-transition:transform 0.2s ease-in-out;--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23052c65' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");--bs-accordion-btn-focus-box-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-accordion-body-padding-x:1.25rem;--bs-accordion-body-padding-y:1rem;--bs-accordion-active-color:var(--bs-primary-text-emphasis);--bs-accordion-active-bg:var(--bs-primary-bg-subtle)}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x);font-size:1rem;color:var(--bs-accordion-btn-color);text-align:left;background-color:var(--bs-accordion-btn-bg);border:0;border-radius:0;overflow-anchor:none;transition:var(--bs-accordion-transition)}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:var(--bs-accordion-active-color);background-color:var(--bs-accordion-active-bg);box-shadow:inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color)}.accordion-button:not(.collapsed)::after{background-image:var(--bs-accordion-btn-active-icon);transform:var(--bs-accordion-btn-icon-transform)}.accordion-button::after{flex-shrink:0;width:var(--bs-accordion-btn-icon-width);height:var(--bs-accordion-btn-icon-width);margin-left:auto;content:"";background-image:var(--bs-accordion-btn-icon);background-repeat:no-repeat;background-size:var(--bs-accordion-btn-icon-width);transition:var(--bs-accordion-btn-icon-transition)}@media (prefers-reduced-motion:reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;outline:0;box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.accordion-header{margin-bottom:0}.accordion-item{color:var(--bs-accordion-color);background-color:var(--bs-accordion-bg);border:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--bs-accordion-border-radius);border-top-right-radius:var(--bs-accordion-border-radius)}.accordion-item:first-of-type>.accordion-header .accordion-button{border-top-left-radius:var(--bs-accordion-inner-border-radius);border-top-right-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-item:last-of-type>.accordion-header .accordion-button.collapsed{border-bottom-right-radius:var(--bs-accordion-inner-border-radius);border-bottom-left-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:last-of-type>.accordion-collapse{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-body{padding:var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x)}.accordion-flush>.accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush>.accordion-item:first-child{border-top:0}.accordion-flush>.accordion-item:last-child{border-bottom:0}.accordion-flush>.accordion-item>.accordion-collapse,.accordion-flush>.accordion-item>.accordion-header .accordion-button,.accordion-flush>.accordion-item>.accordion-header .accordion-button.collapsed{border-radius:0}[data-bs-theme=dark] .accordion-button::after{--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e");--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e")}.breadcrumb{--bs-breadcrumb-padding-x:0;--bs-breadcrumb-padding-y:0;--bs-breadcrumb-margin-bottom:1rem;--bs-breadcrumb-bg: ;--bs-breadcrumb-border-radius: ;--bs-breadcrumb-divider-color:var(--bs-secondary-color);--bs-breadcrumb-item-padding-x:0.5rem;--bs-breadcrumb-item-active-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;padding:var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x);margin-bottom:var(--bs-breadcrumb-margin-bottom);font-size:var(--bs-breadcrumb-font-size);list-style:none;background-color:var(--bs-breadcrumb-bg);border-radius:var(--bs-breadcrumb-border-radius)}.breadcrumb-item+.breadcrumb-item{padding-left:var(--bs-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:var(--bs-breadcrumb-item-padding-x);color:var(--bs-breadcrumb-divider-color);content:var(--bs-breadcrumb-divider, "/")}.breadcrumb-item.active{color:var(--bs-breadcrumb-item-active-color)}.pagination{--bs-pagination-padding-x:0.75rem;--bs-pagination-padding-y:0.375rem;--bs-pagination-font-size:1rem;--bs-pagination-color:var(--bs-link-color);--bs-pagination-bg:var(--bs-body-bg);--bs-pagination-border-width:var(--bs-border-width);--bs-pagination-border-color:var(--bs-border-color);--bs-pagination-border-radius:var(--bs-border-radius);--bs-pagination-hover-color:var(--bs-link-hover-color);--bs-pagination-hover-bg:var(--bs-tertiary-bg);--bs-pagination-hover-border-color:var(--bs-border-color);--bs-pagination-focus-color:var(--bs-link-hover-color);--bs-pagination-focus-bg:var(--bs-secondary-bg);--bs-pagination-focus-box-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-pagination-active-color:#fff;--bs-pagination-active-bg:#0d6efd;--bs-pagination-active-border-color:#0d6efd;--bs-pagination-disabled-color:var(--bs-secondary-color);--bs-pagination-disabled-bg:var(--bs-secondary-bg);--bs-pagination-disabled-border-color:var(--bs-border-color);display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--bs-pagination-padding-y) var(--bs-pagination-padding-x);font-size:var(--bs-pagination-font-size);color:var(--bs-pagination-color);text-decoration:none;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width) solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.active>.page-link,.page-link.active{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);border-color:var(--bs-pagination-active-border-color)}.disabled>.page-link,.page-link.disabled{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:calc(-1 * var(--bs-border-width))}.page-item:first-child .page-link{border-top-left-radius:var(--bs-pagination-border-radius);border-bottom-left-radius:var(--bs-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--bs-pagination-border-radius);border-bottom-right-radius:var(--bs-pagination-border-radius)}.pagination-lg{--bs-pagination-padding-x:1.5rem;--bs-pagination-padding-y:0.75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius:var(--bs-border-radius-lg)}.pagination-sm{--bs-pagination-padding-x:0.5rem;--bs-pagination-padding-y:0.25rem;--bs-pagination-font-size:0.875rem;--bs-pagination-border-radius:var(--bs-border-radius-sm)}.badge{--bs-badge-padding-x:0.65em;--bs-badge-padding-y:0.35em;--bs-badge-font-size:0.75em;--bs-badge-font-weight:700;--bs-badge-color:#fff;--bs-badge-border-radius:var(--bs-border-radius);display:inline-block;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;color:var(--bs-badge-color);text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:var(--bs-badge-border-radius)}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg:transparent;--bs-alert-padding-x:1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:1rem;--bs-alert-color:inherit;--bs-alert-border-color:transparent;--bs-alert-border:var(--bs-border-width) solid var(--bs-alert-border-color);--bs-alert-border-radius:var(--bs-border-radius);--bs-alert-link-color:inherit;position:relative;padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);margin-bottom:var(--bs-alert-margin-bottom);color:var(--bs-alert-color);background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius)}.alert-heading{color:inherit}.alert-link{font-weight:700;color:var(--bs-alert-link-color)}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{--bs-alert-color:var(--bs-primary-text-emphasis);--bs-alert-bg:var(--bs-primary-bg-subtle);--bs-alert-border-color:var(--bs-primary-border-subtle);--bs-alert-link-color:var(--bs-primary-text-emphasis)}.alert-secondary{--bs-alert-color:var(--bs-secondary-text-emphasis);--bs-alert-bg:var(--bs-secondary-bg-subtle);--bs-alert-border-color:var(--bs-secondary-border-subtle);--bs-alert-link-color:var(--bs-secondary-text-emphasis)}.alert-success{--bs-alert-color:var(--bs-success-text-emphasis);--bs-alert-bg:var(--bs-success-bg-subtle);--bs-alert-border-color:var(--bs-success-border-subtle);--bs-alert-link-color:var(--bs-success-text-emphasis)}.alert-info{--bs-alert-color:var(--bs-info-text-emphasis);--bs-alert-bg:var(--bs-info-bg-subtle);--bs-alert-border-color:var(--bs-info-border-subtle);--bs-alert-link-color:var(--bs-info-text-emphasis)}.alert-warning{--bs-alert-color:var(--bs-warning-text-emphasis);--bs-alert-bg:var(--bs-warning-bg-subtle);--bs-alert-border-color:var(--bs-warning-border-subtle);--bs-alert-link-color:var(--bs-warning-text-emphasis)}.alert-danger{--bs-alert-color:var(--bs-danger-text-emphasis);--bs-alert-bg:var(--bs-danger-bg-subtle);--bs-alert-border-color:var(--bs-danger-border-subtle);--bs-alert-link-color:var(--bs-danger-text-emphasis)}.alert-light{--bs-alert-color:var(--bs-light-text-emphasis);--bs-alert-bg:var(--bs-light-bg-subtle);--bs-alert-border-color:var(--bs-light-border-subtle);--bs-alert-link-color:var(--bs-light-text-emphasis)}.alert-dark{--bs-alert-color:var(--bs-dark-text-emphasis);--bs-alert-bg:var(--bs-dark-bg-subtle);--bs-alert-border-color:var(--bs-dark-border-subtle);--bs-alert-link-color:var(--bs-dark-text-emphasis)}@keyframes progress-bar-stripes{0%{background-position-x:var(--bs-progress-height)}}.progress,.progress-stacked{--bs-progress-height:1rem;--bs-progress-font-size:0.75rem;--bs-progress-bg:var(--bs-secondary-bg);--bs-progress-border-radius:var(--bs-border-radius);--bs-progress-box-shadow:var(--bs-box-shadow-inset);--bs-progress-bar-color:#fff;--bs-progress-bar-bg:#0d6efd;--bs-progress-bar-transition:width 0.6s ease;display:flex;height:var(--bs-progress-height);overflow:hidden;font-size:var(--bs-progress-font-size);background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius)}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:var(--bs-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--bs-progress-bar-bg);transition:var(--bs-progress-bar-transition)}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:var(--bs-progress-height) var(--bs-progress-height)}.progress-stacked>.progress{overflow:visible}.progress-stacked>.progress>.progress-bar{width:100%}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.list-group{--bs-list-group-color:var(--bs-body-color);--bs-list-group-bg:var(--bs-body-bg);--bs-list-group-border-color:var(--bs-border-color);--bs-list-group-border-width:var(--bs-border-width);--bs-list-group-border-radius:var(--bs-border-radius);--bs-list-group-item-padding-x:1rem;--bs-list-group-item-padding-y:0.5rem;--bs-list-group-action-color:var(--bs-secondary-color);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-tertiary-bg);--bs-list-group-action-active-color:var(--bs-body-color);--bs-list-group-action-active-bg:var(--bs-secondary-bg);--bs-list-group-disabled-color:var(--bs-secondary-color);--bs-list-group-disabled-bg:var(--bs-body-bg);--bs-list-group-active-color:#fff;--bs-list-group-active-bg:#0d6efd;--bs-list-group-active-border-color:#0d6efd;display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--bs-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item{position:relative;display:block;padding:var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x);color:var(--bs-list-group-color);text-decoration:none;background-color:var(--bs-list-group-bg);border:var(--bs-list-group-border-width) solid var(--bs-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--bs-list-group-disabled-color);pointer-events:none;background-color:var(--bs-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--bs-list-group-active-color);background-color:var(--bs-list-group-active-bg);border-color:var(--bs-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1 * var(--bs-list-group-border-width));border-top-width:var(--bs-list-group-border-width)}.list-group-item-action{width:100%;color:var(--bs-list-group-action-color);text-align:inherit}.list-group-item-action:not(.active):focus,.list-group-item-action:not(.active):hover{z-index:1;color:var(--bs-list-group-action-hover-color);text-decoration:none;background-color:var(--bs-list-group-action-hover-bg)}.list-group-item-action:not(.active):active{color:var(--bs-list-group-action-active-color);background-color:var(--bs-list-group-action-active-bg)}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--bs-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{--bs-list-group-color:var(--bs-primary-text-emphasis);--bs-list-group-bg:var(--bs-primary-bg-subtle);--bs-list-group-border-color:var(--bs-primary-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-primary-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-primary-border-subtle);--bs-list-group-active-color:var(--bs-primary-bg-subtle);--bs-list-group-active-bg:var(--bs-primary-text-emphasis);--bs-list-group-active-border-color:var(--bs-primary-text-emphasis)}.list-group-item-secondary{--bs-list-group-color:var(--bs-secondary-text-emphasis);--bs-list-group-bg:var(--bs-secondary-bg-subtle);--bs-list-group-border-color:var(--bs-secondary-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-secondary-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-secondary-border-subtle);--bs-list-group-active-color:var(--bs-secondary-bg-subtle);--bs-list-group-active-bg:var(--bs-secondary-text-emphasis);--bs-list-group-active-border-color:var(--bs-secondary-text-emphasis)}.list-group-item-success{--bs-list-group-color:var(--bs-success-text-emphasis);--bs-list-group-bg:var(--bs-success-bg-subtle);--bs-list-group-border-color:var(--bs-success-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-success-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-success-border-subtle);--bs-list-group-active-color:var(--bs-success-bg-subtle);--bs-list-group-active-bg:var(--bs-success-text-emphasis);--bs-list-group-active-border-color:var(--bs-success-text-emphasis)}.list-group-item-info{--bs-list-group-color:var(--bs-info-text-emphasis);--bs-list-group-bg:var(--bs-info-bg-subtle);--bs-list-group-border-color:var(--bs-info-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-info-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-info-border-subtle);--bs-list-group-active-color:var(--bs-info-bg-subtle);--bs-list-group-active-bg:var(--bs-info-text-emphasis);--bs-list-group-active-border-color:var(--bs-info-text-emphasis)}.list-group-item-warning{--bs-list-group-color:var(--bs-warning-text-emphasis);--bs-list-group-bg:var(--bs-warning-bg-subtle);--bs-list-group-border-color:var(--bs-warning-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-warning-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-warning-border-subtle);--bs-list-group-active-color:var(--bs-warning-bg-subtle);--bs-list-group-active-bg:var(--bs-warning-text-emphasis);--bs-list-group-active-border-color:var(--bs-warning-text-emphasis)}.list-group-item-danger{--bs-list-group-color:var(--bs-danger-text-emphasis);--bs-list-group-bg:var(--bs-danger-bg-subtle);--bs-list-group-border-color:var(--bs-danger-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-danger-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-danger-border-subtle);--bs-list-group-active-color:var(--bs-danger-bg-subtle);--bs-list-group-active-bg:var(--bs-danger-text-emphasis);--bs-list-group-active-border-color:var(--bs-danger-text-emphasis)}.list-group-item-light{--bs-list-group-color:var(--bs-light-text-emphasis);--bs-list-group-bg:var(--bs-light-bg-subtle);--bs-list-group-border-color:var(--bs-light-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-light-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-light-border-subtle);--bs-list-group-active-color:var(--bs-light-bg-subtle);--bs-list-group-active-bg:var(--bs-light-text-emphasis);--bs-list-group-active-border-color:var(--bs-light-text-emphasis)}.list-group-item-dark{--bs-list-group-color:var(--bs-dark-text-emphasis);--bs-list-group-bg:var(--bs-dark-bg-subtle);--bs-list-group-border-color:var(--bs-dark-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-dark-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-dark-border-subtle);--bs-list-group-active-color:var(--bs-dark-bg-subtle);--bs-list-group-active-bg:var(--bs-dark-text-emphasis);--bs-list-group-active-border-color:var(--bs-dark-text-emphasis)}.btn-close{--bs-btn-close-color:#000;--bs-btn-close-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/%3e%3c/svg%3e");--bs-btn-close-opacity:0.5;--bs-btn-close-hover-opacity:0.75;--bs-btn-close-focus-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-btn-close-focus-opacity:1;--bs-btn-close-disabled-opacity:0.25;box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:var(--bs-btn-close-color);background:transparent var(--bs-btn-close-bg) center/1em auto no-repeat;filter:var(--bs-btn-close-filter);border:0;border-radius:.375rem;opacity:var(--bs-btn-close-opacity)}.btn-close:hover{color:var(--bs-btn-close-color);text-decoration:none;opacity:var(--bs-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity)}.btn-close.disabled,.btn-close:disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:var(--bs-btn-close-disabled-opacity)}.btn-close-white{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}:root,[data-bs-theme=light]{--bs-btn-close-filter: }[data-bs-theme=dark]{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}.toast{--bs-toast-zindex:1090;--bs-toast-padding-x:0.75rem;--bs-toast-padding-y:0.5rem;--bs-toast-spacing:1.5rem;--bs-toast-max-width:350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg:rgba(var(--bs-body-bg-rgb), 0.85);--bs-toast-border-width:var(--bs-border-width);--bs-toast-border-color:var(--bs-border-color-translucent);--bs-toast-border-radius:var(--bs-border-radius);--bs-toast-box-shadow:var(--bs-box-shadow);--bs-toast-header-color:var(--bs-secondary-color);--bs-toast-header-bg:rgba(var(--bs-body-bg-rgb), 0.85);--bs-toast-header-border-color:var(--bs-border-color-translucent);width:var(--bs-toast-max-width);max-width:100%;font-size:var(--bs-toast-font-size);color:var(--bs-toast-color);pointer-events:auto;background-color:var(--bs-toast-bg);background-clip:padding-box;border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);box-shadow:var(--bs-toast-box-shadow);border-radius:var(--bs-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex:1090;position:absolute;z-index:var(--bs-toast-zindex);width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;align-items:center;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x);color:var(--bs-toast-header-color);background-color:var(--bs-toast-header-bg);background-clip:padding-box;border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width))}.toast-header .btn-close{margin-right:calc(-.5 * var(--bs-toast-padding-x));margin-left:var(--bs-toast-padding-x)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:0.5rem;--bs-modal-color:var(--bs-body-color);--bs-modal-bg:var(--bs-body-bg);--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:var(--bs-border-width);--bs-modal-border-radius:var(--bs-border-radius-lg);--bs-modal-box-shadow:var(--bs-box-shadow-sm);--bs-modal-inner-border-radius:calc(var(--bs-border-radius-lg) - (var(--bs-border-width)));--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:var(--bs-border-width);--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:var(--bs-border-width);position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transform:translate(0,-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin) * 2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - var(--bs-modal-margin) * 2)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);outline:0}.modal-backdrop{--bs-backdrop-zindex:1050;--bs-backdrop-bg:#000;--bs-backdrop-opacity:0.5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;flex-shrink:0;align-items:center;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y) * .5) calc(var(--bs-modal-header-padding-x) * .5);margin-top:calc(-.5 * var(--bs-modal-header-padding-y));margin-right:calc(-.5 * var(--bs-modal-header-padding-x));margin-bottom:calc(-.5 * var(--bs-modal-header-padding-y));margin-left:auto}.modal-title{margin-bottom:0;line-height:var(--bs-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;padding:var(--bs-modal-padding)}.modal-footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * .5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap) * .5)}@media (min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:var(--bs-box-shadow)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{--bs-modal-width:800px}}@media (min-width:1200px){.modal-xl{--bs-modal-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-footer,.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media (max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-footer,.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media (max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-footer,.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media (max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-footer,.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-footer,.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-footer,.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex:1080;--bs-tooltip-max-width:200px;--bs-tooltip-padding-x:0.5rem;--bs-tooltip-padding-y:0.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:0.875rem;--bs-tooltip-color:var(--bs-body-bg);--bs-tooltip-bg:var(--bs-emphasis-color);--bs-tooltip-border-radius:var(--bs-border-radius);--bs-tooltip-opacity:0.9;--bs-tooltip-arrow-width:0.8rem;--bs-tooltip-arrow-height:0.4rem;z-index:var(--bs-tooltip-zindex);display:block;margin:var(--bs-tooltip-margin);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--bs-tooltip-arrow-width);height:var(--bs-tooltip-arrow-height)}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:calc(-1 * var(--bs-tooltip-arrow-height))}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before,.bs-tooltip-top .tooltip-arrow::before{top:-1px;border-width:var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-top-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{left:calc(-1 * var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before,.bs-tooltip-end .tooltip-arrow::before{right:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-right-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:calc(-1 * var(--bs-tooltip-arrow-height))}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before,.bs-tooltip-bottom .tooltip-arrow::before{bottom:-1px;border-width:0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-bottom-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{right:calc(-1 * var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before,.bs-tooltip-start .tooltip-arrow::before{left:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) 0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-left-color:var(--bs-tooltip-bg)}.tooltip-inner{max-width:var(--bs-tooltip-max-width);padding:var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x);color:var(--bs-tooltip-color);text-align:center;background-color:var(--bs-tooltip-bg);border-radius:var(--bs-tooltip-border-radius)}.popover{--bs-popover-zindex:1070;--bs-popover-max-width:276px;--bs-popover-font-size:0.875rem;--bs-popover-bg:var(--bs-body-bg);--bs-popover-border-width:var(--bs-border-width);--bs-popover-border-color:var(--bs-border-color-translucent);--bs-popover-border-radius:var(--bs-border-radius-lg);--bs-popover-inner-border-radius:calc(var(--bs-border-radius-lg) - var(--bs-border-width));--bs-popover-box-shadow:var(--bs-box-shadow);--bs-popover-header-padding-x:1rem;--bs-popover-header-padding-y:0.5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color:inherit;--bs-popover-header-bg:var(--bs-secondary-bg);--bs-popover-body-padding-x:1rem;--bs-popover-body-padding-y:1rem;--bs-popover-body-color:var(--bs-body-color);--bs-popover-arrow-width:1rem;--bs-popover-arrow-height:0.5rem;--bs-popover-arrow-border:var(--bs-popover-border-color);z-index:var(--bs-popover-zindex);display:block;max-width:var(--bs-popover-max-width);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-popover-font-size);word-wrap:break-word;background-color:var(--bs-popover-bg);background-clip:padding-box;border:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-radius:var(--bs-popover-border-radius)}.popover .popover-arrow{display:block;width:var(--bs-popover-arrow-width);height:var(--bs-popover-arrow-height)}.popover .popover-arrow::after,.popover .popover-arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid;border-width:0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::after,.bs-popover-top>.popover-arrow::before{border-width:var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::before{bottom:0;border-top-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-top>.popover-arrow::after{bottom:var(--bs-popover-border-width);border-top-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{left:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::after,.bs-popover-end>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::before{left:0;border-right-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-end>.popover-arrow::after{left:var(--bs-popover-border-width);border-right-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::before{border-width:0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::before{top:0;border-bottom-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::after{top:var(--bs-popover-border-width);border-bottom-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:var(--bs-popover-arrow-width);margin-left:calc(-.5 * var(--bs-popover-arrow-width));content:"";border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-header-bg)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{right:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::after,.bs-popover-start>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) 0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::before{right:0;border-left-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-start>.popover-arrow::after{right:var(--bs-popover-border-width);border-left-color:var(--bs-popover-bg)}.popover-header{padding:var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x);margin-bottom:0;font-size:var(--bs-popover-header-font-size);color:var(--bs-popover-header-color);background-color:var(--bs-popover-header-bg);border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-top-left-radius:var(--bs-popover-inner-border-radius);border-top-right-radius:var(--bs-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x);color:var(--bs-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){transform:translateX(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;filter:var(--bs-carousel-control-icon-filter);border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:var(--bs-carousel-indicator-active-bg);background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:var(--bs-carousel-caption-color);text-align:center}.carousel-dark{--bs-carousel-indicator-active-bg:#000;--bs-carousel-caption-color:#000;--bs-carousel-control-icon-filter:invert(1) grayscale(100)}:root,[data-bs-theme=light]{--bs-carousel-indicator-active-bg:#fff;--bs-carousel-caption-color:#fff;--bs-carousel-control-icon-filter: }[data-bs-theme=dark]{--bs-carousel-indicator-active-bg:#000;--bs-carousel-caption-color:#000;--bs-carousel-control-icon-filter:invert(1) grayscale(100)}.spinner-border,.spinner-grow{display:inline-block;flex-shrink:0;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-border-width:0.25em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-border;border:var(--bs-spinner-border-width) solid currentcolor;border-right-color:transparent}.spinner-border-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem;--bs-spinner-border-width:0.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{--bs-spinner-animation-speed:1.5s}}.offcanvas,.offcanvas-lg,.offcanvas-md,.offcanvas-sm,.offcanvas-xl,.offcanvas-xxl{--bs-offcanvas-zindex:1045;--bs-offcanvas-width:400px;--bs-offcanvas-height:30vh;--bs-offcanvas-padding-x:1rem;--bs-offcanvas-padding-y:1rem;--bs-offcanvas-color:var(--bs-body-color);--bs-offcanvas-bg:var(--bs-body-bg);--bs-offcanvas-border-width:var(--bs-border-width);--bs-offcanvas-border-color:var(--bs-border-color-translucent);--bs-offcanvas-box-shadow:var(--bs-box-shadow-sm);--bs-offcanvas-transition:transform 0.3s ease-in-out;--bs-offcanvas-title-line-height:1.5}@media (max-width:575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:575.98px) and (prefers-reduced-motion:reduce){.offcanvas-sm{transition:none}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.show:not(.hiding),.offcanvas-sm.showing{transform:none}.offcanvas-sm.hiding,.offcanvas-sm.show,.offcanvas-sm.showing{visibility:visible}}@media (min-width:576px){.offcanvas-sm{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:767.98px) and (prefers-reduced-motion:reduce){.offcanvas-md{transition:none}}@media (max-width:767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.show:not(.hiding),.offcanvas-md.showing{transform:none}.offcanvas-md.hiding,.offcanvas-md.show,.offcanvas-md.showing{visibility:visible}}@media (min-width:768px){.offcanvas-md{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:991.98px) and (prefers-reduced-motion:reduce){.offcanvas-lg{transition:none}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.show:not(.hiding),.offcanvas-lg.showing{transform:none}.offcanvas-lg.hiding,.offcanvas-lg.show,.offcanvas-lg.showing{visibility:visible}}@media (min-width:992px){.offcanvas-lg{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:1199.98px) and (prefers-reduced-motion:reduce){.offcanvas-xl{transition:none}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.show:not(.hiding),.offcanvas-xl.showing{transform:none}.offcanvas-xl.hiding,.offcanvas-xl.show,.offcanvas-xl.showing{visibility:visible}}@media (min-width:1200px){.offcanvas-xl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:1399.98px) and (prefers-reduced-motion:reduce){.offcanvas-xxl{transition:none}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.show:not(.hiding),.offcanvas-xxl.showing{transform:none}.offcanvas-xxl.hiding,.offcanvas-xxl.show,.offcanvas-xxl.showing{visibility:visible}}@media (min-width:1400px){.offcanvas-xxl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}.offcanvas{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}@media (prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.show:not(.hiding),.offcanvas.showing{transform:none}.offcanvas.hiding,.offcanvas.show,.offcanvas.showing{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;align-items:center;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--bs-offcanvas-padding-y) * .5) calc(var(--bs-offcanvas-padding-x) * .5);margin-top:calc(-.5 * var(--bs-offcanvas-padding-y));margin-right:calc(-.5 * var(--bs-offcanvas-padding-x));margin-bottom:calc(-.5 * var(--bs-offcanvas-padding-y));margin-left:auto}.offcanvas-title{margin-bottom:0;line-height:var(--bs-offcanvas-title-line-height)}.offcanvas-body{flex-grow:1;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{-webkit-mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{-webkit-mask-position:-200% 0%;mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.text-bg-primary{color:#fff!important;background-color:RGBA(var(--bs-primary-rgb),var(--bs-bg-opacity,1))!important}.text-bg-secondary{color:#fff!important;background-color:RGBA(var(--bs-secondary-rgb),var(--bs-bg-opacity,1))!important}.text-bg-success{color:#fff!important;background-color:RGBA(var(--bs-success-rgb),var(--bs-bg-opacity,1))!important}.text-bg-info{color:#000!important;background-color:RGBA(var(--bs-info-rgb),var(--bs-bg-opacity,1))!important}.text-bg-warning{color:#000!important;background-color:RGBA(var(--bs-warning-rgb),var(--bs-bg-opacity,1))!important}.text-bg-danger{color:#fff!important;background-color:RGBA(var(--bs-danger-rgb),var(--bs-bg-opacity,1))!important}.text-bg-light{color:#000!important;background-color:RGBA(var(--bs-light-rgb),var(--bs-bg-opacity,1))!important}.text-bg-dark{color:#fff!important;background-color:RGBA(var(--bs-dark-rgb),var(--bs-bg-opacity,1))!important}.link-primary{color:RGBA(var(--bs-primary-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-primary-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-primary-rgb),var(--bs-link-underline-opacity,1))!important}.link-primary:focus,.link-primary:hover{color:RGBA(10,88,202,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(10,88,202,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(10,88,202,var(--bs-link-underline-opacity,1))!important}.link-secondary{color:RGBA(var(--bs-secondary-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-secondary-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-secondary-rgb),var(--bs-link-underline-opacity,1))!important}.link-secondary:focus,.link-secondary:hover{color:RGBA(86,94,100,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(86,94,100,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(86,94,100,var(--bs-link-underline-opacity,1))!important}.link-success{color:RGBA(var(--bs-success-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-success-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-success-rgb),var(--bs-link-underline-opacity,1))!important}.link-success:focus,.link-success:hover{color:RGBA(20,108,67,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(20,108,67,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(20,108,67,var(--bs-link-underline-opacity,1))!important}.link-info{color:RGBA(var(--bs-info-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-info-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-info-rgb),var(--bs-link-underline-opacity,1))!important}.link-info:focus,.link-info:hover{color:RGBA(61,213,243,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(61,213,243,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(61,213,243,var(--bs-link-underline-opacity,1))!important}.link-warning{color:RGBA(var(--bs-warning-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-warning-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-warning-rgb),var(--bs-link-underline-opacity,1))!important}.link-warning:focus,.link-warning:hover{color:RGBA(255,205,57,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(255,205,57,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(255,205,57,var(--bs-link-underline-opacity,1))!important}.link-danger{color:RGBA(var(--bs-danger-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-danger-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-danger-rgb),var(--bs-link-underline-opacity,1))!important}.link-danger:focus,.link-danger:hover{color:RGBA(176,42,55,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(176,42,55,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(176,42,55,var(--bs-link-underline-opacity,1))!important}.link-light{color:RGBA(var(--bs-light-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-light-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-light-rgb),var(--bs-link-underline-opacity,1))!important}.link-light:focus,.link-light:hover{color:RGBA(249,250,251,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(249,250,251,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(249,250,251,var(--bs-link-underline-opacity,1))!important}.link-dark{color:RGBA(var(--bs-dark-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-dark-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-dark-rgb),var(--bs-link-underline-opacity,1))!important}.link-dark:focus,.link-dark:hover{color:RGBA(26,30,33,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(26,30,33,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(26,30,33,var(--bs-link-underline-opacity,1))!important}.link-body-emphasis{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,1))!important}.link-body-emphasis:focus,.link-body-emphasis:hover{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity,.75))!important;-webkit-text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,0.75))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,0.75))!important}.focus-ring:focus{outline:0;box-shadow:var(--bs-focus-ring-x,0) var(--bs-focus-ring-y,0) var(--bs-focus-ring-blur,0) var(--bs-focus-ring-width) var(--bs-focus-ring-color)}.icon-link{display:inline-flex;gap:.375rem;align-items:center;-webkit-text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,0.5));text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,0.5));text-underline-offset:0.25em;-webkit-backface-visibility:hidden;backface-visibility:hidden}.icon-link>.bi{flex-shrink:0;width:1em;height:1em;fill:currentcolor;transition:.2s ease-in-out transform}@media (prefers-reduced-motion:reduce){.icon-link>.bi{transition:none}}.icon-link-hover:focus-visible>.bi,.icon-link-hover:hover>.bi{transform:var(--bs-icon-link-transform,translate3d(.25em,0,0))}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:75%}.ratio-16x9{--bs-aspect-ratio:56.25%}.ratio-21x9{--bs-aspect-ratio:42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:1 1 auto;flex-direction:column;align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption),.visually-hidden:not(caption){position:absolute!important}.visually-hidden *,.visually-hidden-focusable:not(:focus):not(:focus-within) *{overflow:hidden!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;width:var(--bs-border-width);min-height:1em;background-color:currentcolor;opacity:.25}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.object-fit-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-none{-o-object-fit:none!important;object-fit:none!important}.opacity-0{opacity:0!important}.opacity-25{opacity:.25!important}.opacity-50{opacity:.5!important}.opacity-75{opacity:.75!important}.opacity-100{opacity:1!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.overflow-x-auto{overflow-x:auto!important}.overflow-x-hidden{overflow-x:hidden!important}.overflow-x-visible{overflow-x:visible!important}.overflow-x-scroll{overflow-x:scroll!important}.overflow-y-auto{overflow-y:auto!important}.overflow-y-hidden{overflow-y:hidden!important}.overflow-y-visible{overflow-y:visible!important}.overflow-y-scroll{overflow-y:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-inline-grid{display:inline-grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:var(--bs-box-shadow)!important}.shadow-sm{box-shadow:var(--bs-box-shadow-sm)!important}.shadow-lg{box-shadow:var(--bs-box-shadow-lg)!important}.shadow-none{box-shadow:none!important}.focus-ring-primary{--bs-focus-ring-color:rgba(var(--bs-primary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-secondary{--bs-focus-ring-color:rgba(var(--bs-secondary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-success{--bs-focus-ring-color:rgba(var(--bs-success-rgb), var(--bs-focus-ring-opacity))}.focus-ring-info{--bs-focus-ring-color:rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity))}.focus-ring-warning{--bs-focus-ring-color:rgba(var(--bs-warning-rgb), var(--bs-focus-ring-opacity))}.focus-ring-danger{--bs-focus-ring-color:rgba(var(--bs-danger-rgb), var(--bs-focus-ring-opacity))}.focus-ring-light{--bs-focus-ring-color:rgba(var(--bs-light-rgb), var(--bs-focus-ring-opacity))}.focus-ring-dark{--bs-focus-ring-color:rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity))}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translateX(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-0{border:0!important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-top-0{border-top:0!important}.border-end{border-right:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-start-0{border-left:0!important}.border-primary{--bs-border-opacity:1;border-color:rgba(var(--bs-primary-rgb),var(--bs-border-opacity))!important}.border-secondary{--bs-border-opacity:1;border-color:rgba(var(--bs-secondary-rgb),var(--bs-border-opacity))!important}.border-success{--bs-border-opacity:1;border-color:rgba(var(--bs-success-rgb),var(--bs-border-opacity))!important}.border-info{--bs-border-opacity:1;border-color:rgba(var(--bs-info-rgb),var(--bs-border-opacity))!important}.border-warning{--bs-border-opacity:1;border-color:rgba(var(--bs-warning-rgb),var(--bs-border-opacity))!important}.border-danger{--bs-border-opacity:1;border-color:rgba(var(--bs-danger-rgb),var(--bs-border-opacity))!important}.border-light{--bs-border-opacity:1;border-color:rgba(var(--bs-light-rgb),var(--bs-border-opacity))!important}.border-dark{--bs-border-opacity:1;border-color:rgba(var(--bs-dark-rgb),var(--bs-border-opacity))!important}.border-black{--bs-border-opacity:1;border-color:rgba(var(--bs-black-rgb),var(--bs-border-opacity))!important}.border-white{--bs-border-opacity:1;border-color:rgba(var(--bs-white-rgb),var(--bs-border-opacity))!important}.border-primary-subtle{border-color:var(--bs-primary-border-subtle)!important}.border-secondary-subtle{border-color:var(--bs-secondary-border-subtle)!important}.border-success-subtle{border-color:var(--bs-success-border-subtle)!important}.border-info-subtle{border-color:var(--bs-info-border-subtle)!important}.border-warning-subtle{border-color:var(--bs-warning-border-subtle)!important}.border-danger-subtle{border-color:var(--bs-danger-border-subtle)!important}.border-light-subtle{border-color:var(--bs-light-border-subtle)!important}.border-dark-subtle{border-color:var(--bs-dark-border-subtle)!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.border-opacity-10{--bs-border-opacity:0.1}.border-opacity-25{--bs-border-opacity:0.25}.border-opacity-50{--bs-border-opacity:0.5}.border-opacity-75{--bs-border-opacity:0.75}.border-opacity-100{--bs-border-opacity:1}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.row-gap-0{row-gap:0!important}.row-gap-1{row-gap:.25rem!important}.row-gap-2{row-gap:.5rem!important}.row-gap-3{row-gap:1rem!important}.row-gap-4{row-gap:1.5rem!important}.row-gap-5{row-gap:3rem!important}.column-gap-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-lighter{font-weight:lighter!important}.fw-light{font-weight:300!important}.fw-normal{font-weight:400!important}.fw-medium{font-weight:500!important}.fw-semibold{font-weight:600!important}.fw-bold{font-weight:700!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-color-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-black-50{--bs-text-opacity:1;color:rgba(0,0,0,.5)!important}.text-white-50{--bs-text-opacity:1;color:rgba(255,255,255,.5)!important}.text-body-secondary{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-body-tertiary{--bs-text-opacity:1;color:var(--bs-tertiary-color)!important}.text-body-emphasis{--bs-text-opacity:1;color:var(--bs-emphasis-color)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:0.25}.text-opacity-50{--bs-text-opacity:0.5}.text-opacity-75{--bs-text-opacity:0.75}.text-opacity-100{--bs-text-opacity:1}.text-primary-emphasis{color:var(--bs-primary-text-emphasis)!important}.text-secondary-emphasis{color:var(--bs-secondary-text-emphasis)!important}.text-success-emphasis{color:var(--bs-success-text-emphasis)!important}.text-info-emphasis{color:var(--bs-info-text-emphasis)!important}.text-warning-emphasis{color:var(--bs-warning-text-emphasis)!important}.text-danger-emphasis{color:var(--bs-danger-text-emphasis)!important}.text-light-emphasis{color:var(--bs-light-text-emphasis)!important}.text-dark-emphasis{color:var(--bs-dark-text-emphasis)!important}.link-opacity-10{--bs-link-opacity:0.1}.link-opacity-10-hover:hover{--bs-link-opacity:0.1}.link-opacity-25{--bs-link-opacity:0.25}.link-opacity-25-hover:hover{--bs-link-opacity:0.25}.link-opacity-50{--bs-link-opacity:0.5}.link-opacity-50-hover:hover{--bs-link-opacity:0.5}.link-opacity-75{--bs-link-opacity:0.75}.link-opacity-75-hover:hover{--bs-link-opacity:0.75}.link-opacity-100{--bs-link-opacity:1}.link-opacity-100-hover:hover{--bs-link-opacity:1}.link-offset-1{text-underline-offset:0.125em!important}.link-offset-1-hover:hover{text-underline-offset:0.125em!important}.link-offset-2{text-underline-offset:0.25em!important}.link-offset-2-hover:hover{text-underline-offset:0.25em!important}.link-offset-3{text-underline-offset:0.375em!important}.link-offset-3-hover:hover{text-underline-offset:0.375em!important}.link-underline-primary{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-primary-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-primary-rgb),var(--bs-link-underline-opacity))!important}.link-underline-secondary{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-secondary-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-secondary-rgb),var(--bs-link-underline-opacity))!important}.link-underline-success{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-success-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-success-rgb),var(--bs-link-underline-opacity))!important}.link-underline-info{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-info-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-info-rgb),var(--bs-link-underline-opacity))!important}.link-underline-warning{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-warning-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-warning-rgb),var(--bs-link-underline-opacity))!important}.link-underline-danger{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-danger-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-danger-rgb),var(--bs-link-underline-opacity))!important}.link-underline-light{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-light-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-light-rgb),var(--bs-link-underline-opacity))!important}.link-underline-dark{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-dark-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-dark-rgb),var(--bs-link-underline-opacity))!important}.link-underline{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-underline-opacity,1))!important}.link-underline-opacity-0{--bs-link-underline-opacity:0}.link-underline-opacity-0-hover:hover{--bs-link-underline-opacity:0}.link-underline-opacity-10{--bs-link-underline-opacity:0.1}.link-underline-opacity-10-hover:hover{--bs-link-underline-opacity:0.1}.link-underline-opacity-25{--bs-link-underline-opacity:0.25}.link-underline-opacity-25-hover:hover{--bs-link-underline-opacity:0.25}.link-underline-opacity-50{--bs-link-underline-opacity:0.5}.link-underline-opacity-50-hover:hover{--bs-link-underline-opacity:0.5}.link-underline-opacity-75{--bs-link-underline-opacity:0.75}.link-underline-opacity-75-hover:hover{--bs-link-underline-opacity:0.75}.link-underline-opacity-100{--bs-link-underline-opacity:1}.link-underline-opacity-100-hover:hover{--bs-link-underline-opacity:1}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-info{--bs-bg-opacity:1;background-color:rgba(var(--bs-info-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.bg-light{--bs-bg-opacity:1;background-color:rgba(var(--bs-light-rgb),var(--bs-bg-opacity))!important}.bg-dark{--bs-bg-opacity:1;background-color:rgba(var(--bs-dark-rgb),var(--bs-bg-opacity))!important}.bg-black{--bs-bg-opacity:1;background-color:rgba(var(--bs-black-rgb),var(--bs-bg-opacity))!important}.bg-white{--bs-bg-opacity:1;background-color:rgba(var(--bs-white-rgb),var(--bs-bg-opacity))!important}.bg-body{--bs-bg-opacity:1;background-color:rgba(var(--bs-body-bg-rgb),var(--bs-bg-opacity))!important}.bg-transparent{--bs-bg-opacity:1;background-color:transparent!important}.bg-body-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-bg-rgb),var(--bs-bg-opacity))!important}.bg-body-tertiary{--bs-bg-opacity:1;background-color:rgba(var(--bs-tertiary-bg-rgb),var(--bs-bg-opacity))!important}.bg-opacity-10{--bs-bg-opacity:0.1}.bg-opacity-25{--bs-bg-opacity:0.25}.bg-opacity-50{--bs-bg-opacity:0.5}.bg-opacity-75{--bs-bg-opacity:0.75}.bg-opacity-100{--bs-bg-opacity:1}.bg-primary-subtle{background-color:var(--bs-primary-bg-subtle)!important}.bg-secondary-subtle{background-color:var(--bs-secondary-bg-subtle)!important}.bg-success-subtle{background-color:var(--bs-success-bg-subtle)!important}.bg-info-subtle{background-color:var(--bs-info-bg-subtle)!important}.bg-warning-subtle{background-color:var(--bs-warning-bg-subtle)!important}.bg-danger-subtle{background-color:var(--bs-danger-bg-subtle)!important}.bg-light-subtle{background-color:var(--bs-light-bg-subtle)!important}.bg-dark-subtle{background-color:var(--bs-dark-bg-subtle)!important}.bg-gradient{background-image:var(--bs-gradient)!important}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:var(--bs-border-radius)!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:var(--bs-border-radius-sm)!important}.rounded-2{border-radius:var(--bs-border-radius)!important}.rounded-3{border-radius:var(--bs-border-radius-lg)!important}.rounded-4{border-radius:var(--bs-border-radius-xl)!important}.rounded-5{border-radius:var(--bs-border-radius-xxl)!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:var(--bs-border-radius-pill)!important}.rounded-top{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-top-0{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-top-1{border-top-left-radius:var(--bs-border-radius-sm)!important;border-top-right-radius:var(--bs-border-radius-sm)!important}.rounded-top-2{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-top-3{border-top-left-radius:var(--bs-border-radius-lg)!important;border-top-right-radius:var(--bs-border-radius-lg)!important}.rounded-top-4{border-top-left-radius:var(--bs-border-radius-xl)!important;border-top-right-radius:var(--bs-border-radius-xl)!important}.rounded-top-5{border-top-left-radius:var(--bs-border-radius-xxl)!important;border-top-right-radius:var(--bs-border-radius-xxl)!important}.rounded-top-circle{border-top-left-radius:50%!important;border-top-right-radius:50%!important}.rounded-top-pill{border-top-left-radius:var(--bs-border-radius-pill)!important;border-top-right-radius:var(--bs-border-radius-pill)!important}.rounded-end{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-end-0{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.rounded-end-1{border-top-right-radius:var(--bs-border-radius-sm)!important;border-bottom-right-radius:var(--bs-border-radius-sm)!important}.rounded-end-2{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-end-3{border-top-right-radius:var(--bs-border-radius-lg)!important;border-bottom-right-radius:var(--bs-border-radius-lg)!important}.rounded-end-4{border-top-right-radius:var(--bs-border-radius-xl)!important;border-bottom-right-radius:var(--bs-border-radius-xl)!important}.rounded-end-5{border-top-right-radius:var(--bs-border-radius-xxl)!important;border-bottom-right-radius:var(--bs-border-radius-xxl)!important}.rounded-end-circle{border-top-right-radius:50%!important;border-bottom-right-radius:50%!important}.rounded-end-pill{border-top-right-radius:var(--bs-border-radius-pill)!important;border-bottom-right-radius:var(--bs-border-radius-pill)!important}.rounded-bottom{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-bottom-0{border-bottom-right-radius:0!important;border-bottom-left-radius:0!important}.rounded-bottom-1{border-bottom-right-radius:var(--bs-border-radius-sm)!important;border-bottom-left-radius:var(--bs-border-radius-sm)!important}.rounded-bottom-2{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-bottom-3{border-bottom-right-radius:var(--bs-border-radius-lg)!important;border-bottom-left-radius:var(--bs-border-radius-lg)!important}.rounded-bottom-4{border-bottom-right-radius:var(--bs-border-radius-xl)!important;border-bottom-left-radius:var(--bs-border-radius-xl)!important}.rounded-bottom-5{border-bottom-right-radius:var(--bs-border-radius-xxl)!important;border-bottom-left-radius:var(--bs-border-radius-xxl)!important}.rounded-bottom-circle{border-bottom-right-radius:50%!important;border-bottom-left-radius:50%!important}.rounded-bottom-pill{border-bottom-right-radius:var(--bs-border-radius-pill)!important;border-bottom-left-radius:var(--bs-border-radius-pill)!important}.rounded-start{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.rounded-start-0{border-bottom-left-radius:0!important;border-top-left-radius:0!important}.rounded-start-1{border-bottom-left-radius:var(--bs-border-radius-sm)!important;border-top-left-radius:var(--bs-border-radius-sm)!important}.rounded-start-2{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.rounded-start-3{border-bottom-left-radius:var(--bs-border-radius-lg)!important;border-top-left-radius:var(--bs-border-radius-lg)!important}.rounded-start-4{border-bottom-left-radius:var(--bs-border-radius-xl)!important;border-top-left-radius:var(--bs-border-radius-xl)!important}.rounded-start-5{border-bottom-left-radius:var(--bs-border-radius-xxl)!important;border-top-left-radius:var(--bs-border-radius-xxl)!important}.rounded-start-circle{border-bottom-left-radius:50%!important;border-top-left-radius:50%!important}.rounded-start-pill{border-bottom-left-radius:var(--bs-border-radius-pill)!important;border-top-left-radius:var(--bs-border-radius-pill)!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}.z-n1{z-index:-1!important}.z-0{z-index:0!important}.z-1{z-index:1!important}.z-2{z-index:2!important}.z-3{z-index:3!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.object-fit-sm-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-sm-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-sm-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-sm-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-sm-none{-o-object-fit:none!important;object-fit:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-inline-grid{display:inline-grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.row-gap-sm-0{row-gap:0!important}.row-gap-sm-1{row-gap:.25rem!important}.row-gap-sm-2{row-gap:.5rem!important}.row-gap-sm-3{row-gap:1rem!important}.row-gap-sm-4{row-gap:1.5rem!important}.row-gap-sm-5{row-gap:3rem!important}.column-gap-sm-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-sm-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-sm-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-sm-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-sm-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-sm-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.object-fit-md-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-md-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-md-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-md-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-md-none{-o-object-fit:none!important;object-fit:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-inline-grid{display:inline-grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.row-gap-md-0{row-gap:0!important}.row-gap-md-1{row-gap:.25rem!important}.row-gap-md-2{row-gap:.5rem!important}.row-gap-md-3{row-gap:1rem!important}.row-gap-md-4{row-gap:1.5rem!important}.row-gap-md-5{row-gap:3rem!important}.column-gap-md-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-md-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-md-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-md-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-md-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-md-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.object-fit-lg-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-lg-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-lg-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-lg-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-lg-none{-o-object-fit:none!important;object-fit:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-inline-grid{display:inline-grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.row-gap-lg-0{row-gap:0!important}.row-gap-lg-1{row-gap:.25rem!important}.row-gap-lg-2{row-gap:.5rem!important}.row-gap-lg-3{row-gap:1rem!important}.row-gap-lg-4{row-gap:1.5rem!important}.row-gap-lg-5{row-gap:3rem!important}.column-gap-lg-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-lg-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-lg-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-lg-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-lg-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-lg-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.object-fit-xl-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-xl-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-xl-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-xl-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-xl-none{-o-object-fit:none!important;object-fit:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-inline-grid{display:inline-grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.row-gap-xl-0{row-gap:0!important}.row-gap-xl-1{row-gap:.25rem!important}.row-gap-xl-2{row-gap:.5rem!important}.row-gap-xl-3{row-gap:1rem!important}.row-gap-xl-4{row-gap:1.5rem!important}.row-gap-xl-5{row-gap:3rem!important}.column-gap-xl-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-xl-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-xl-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-xl-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-xl-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-xl-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.object-fit-xxl-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-xxl-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-xxl-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-xxl-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-xxl-none{-o-object-fit:none!important;object-fit:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-inline-grid{display:inline-grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.row-gap-xxl-0{row-gap:0!important}.row-gap-xxl-1{row-gap:.25rem!important}.row-gap-xxl-2{row-gap:.5rem!important}.row-gap-xxl-3{row-gap:1rem!important}.row-gap-xxl-4{row-gap:1.5rem!important}.row-gap-xxl-5{row-gap:3rem!important}.column-gap-xxl-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-xxl-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-xxl-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-xxl-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-xxl-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-xxl-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-inline-grid{display:inline-grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}} /*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.css b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.css deleted file mode 100644 index d344f78a39748..0000000000000 --- a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.css +++ /dev/null @@ -1 +0,0 @@ -:root{--dt-row-selected: 2, 117, 216;--dt-row-selected-text: 255, 255, 255;--dt-row-selected-link: 9, 10, 11;--dt-row-stripe: 0, 0, 0;--dt-row-hover: 0, 0, 0;--dt-column-ordering: 0, 0, 0;--dt-html-background: white}:root.dark{--dt-html-background: rgb(33, 37, 41)}table.dataTable td.dt-control{text-align:center;cursor:pointer}table.dataTable td.dt-control:before{display:inline-block;color:rgba(0, 0, 0, 0.5);content:"▶"}table.dataTable tr.dt-hasChild td.dt-control:before{content:"▼"}html.dark table.dataTable td.dt-control:before,:root[data-bs-theme=dark] table.dataTable td.dt-control:before{color:rgba(255, 255, 255, 0.5)}html.dark table.dataTable tr.dt-hasChild td.dt-control:before,:root[data-bs-theme=dark] table.dataTable tr.dt-hasChild td.dt-control:before{color:rgba(255, 255, 255, 0.5)}table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting_asc_disabled,table.dataTable thead>tr>th.sorting_desc_disabled,table.dataTable thead>tr>td.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting_asc_disabled,table.dataTable thead>tr>td.sorting_desc_disabled{cursor:pointer;position:relative;padding-right:26px}table.dataTable thead>tr>th.sorting:before,table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>th.sorting_desc:before,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>th.sorting_asc_disabled:after,table.dataTable thead>tr>th.sorting_desc_disabled:before,table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting:before,table.dataTable thead>tr>td.sorting:after,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_asc:after,table.dataTable thead>tr>td.sorting_desc:before,table.dataTable thead>tr>td.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_asc_disabled:after,table.dataTable thead>tr>td.sorting_desc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:after{position:absolute;display:block;opacity:.125;right:10px;line-height:9px;font-size:.8em}table.dataTable thead>tr>th.sorting:before,table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_desc:before,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>th.sorting_desc_disabled:before,table.dataTable thead>tr>td.sorting:before,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_desc:before,table.dataTable thead>tr>td.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:before{bottom:50%;content:"▲";content:"▲"/""}table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>th.sorting_asc_disabled:after,table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting:after,table.dataTable thead>tr>td.sorting_asc:after,table.dataTable thead>tr>td.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc_disabled:after,table.dataTable thead>tr>td.sorting_desc_disabled:after{top:50%;content:"▼";content:"▼"/""}table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_desc:after{opacity:.6}table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting_asc_disabled:before{display:none}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}div.dataTables_scrollBody>table.dataTable>thead>tr>th:before,div.dataTables_scrollBody>table.dataTable>thead>tr>th:after,div.dataTables_scrollBody>table.dataTable>thead>tr>td:before,div.dataTables_scrollBody>table.dataTable>thead>tr>td:after{display:none}div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:2px;z-index:10}div.dataTables_processing>div:last-child{position:relative;width:80px;height:15px;margin:1em auto}div.dataTables_processing>div:last-child>div{position:absolute;top:0;width:13px;height:13px;border-radius:50%;background:rgb(2, 117, 216);background:rgb(var(--dt-row-selected));animation-timing-function:cubic-bezier(0, 1, 1, 0)}div.dataTables_processing>div:last-child>div:nth-child(1){left:8px;animation:datatables-loader-1 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(2){left:8px;animation:datatables-loader-2 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(3){left:32px;animation:datatables-loader-2 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(4){left:56px;animation:datatables-loader-3 .6s infinite}@keyframes datatables-loader-1{0%{transform:scale(0)}100%{transform:scale(1)}}@keyframes datatables-loader-3{0%{transform:scale(1)}100%{transform:scale(0)}}@keyframes datatables-loader-2{0%{transform:translate(0, 0)}100%{transform:translate(24px, 0)}}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}table.dataTable th.dt-left,table.dataTable td.dt-left{text-align:left}table.dataTable th.dt-center,table.dataTable td.dt-center,table.dataTable td.dataTables_empty{text-align:center}table.dataTable th.dt-right,table.dataTable td.dt-right{text-align:right}table.dataTable th.dt-justify,table.dataTable td.dt-justify{text-align:justify}table.dataTable th.dt-nowrap,table.dataTable td.dt-nowrap{white-space:nowrap}table.dataTable thead th,table.dataTable thead td,table.dataTable tfoot th,table.dataTable tfoot td{text-align:left}table.dataTable thead th.dt-head-left,table.dataTable thead td.dt-head-left,table.dataTable tfoot th.dt-head-left,table.dataTable tfoot td.dt-head-left{text-align:left}table.dataTable thead th.dt-head-center,table.dataTable thead td.dt-head-center,table.dataTable tfoot th.dt-head-center,table.dataTable tfoot td.dt-head-center{text-align:center}table.dataTable thead th.dt-head-right,table.dataTable thead td.dt-head-right,table.dataTable tfoot th.dt-head-right,table.dataTable tfoot td.dt-head-right{text-align:right}table.dataTable thead th.dt-head-justify,table.dataTable thead td.dt-head-justify,table.dataTable tfoot th.dt-head-justify,table.dataTable tfoot td.dt-head-justify{text-align:justify}table.dataTable thead th.dt-head-nowrap,table.dataTable thead td.dt-head-nowrap,table.dataTable tfoot th.dt-head-nowrap,table.dataTable tfoot td.dt-head-nowrap{white-space:nowrap}table.dataTable tbody th.dt-body-left,table.dataTable tbody td.dt-body-left{text-align:left}table.dataTable tbody th.dt-body-center,table.dataTable tbody td.dt-body-center{text-align:center}table.dataTable tbody th.dt-body-right,table.dataTable tbody td.dt-body-right{text-align:right}table.dataTable tbody th.dt-body-justify,table.dataTable tbody td.dt-body-justify{text-align:justify}table.dataTable tbody th.dt-body-nowrap,table.dataTable tbody td.dt-body-nowrap{white-space:nowrap}table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important;border-collapse:separate !important;border-spacing:0}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}table.dataTable.table-striped>tbody>tr:nth-of-type(2n+1){background-color:transparent}table.dataTable>tbody>tr{background-color:transparent}table.dataTable>tbody>tr.selected>*{box-shadow:inset 0 0 0 9999px rgb(2, 117, 216);box-shadow:inset 0 0 0 9999px rgb(var(--dt-row-selected));color:rgb(255, 255, 255);color:rgb(var(--dt-row-selected-text))}table.dataTable>tbody>tr.selected a{color:rgb(9, 10, 11);color:rgb(var(--dt-row-selected-link))}table.dataTable.table-striped>tbody>tr.odd>*{box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-stripe), 0.05)}table.dataTable.table-striped>tbody>tr.odd.selected>*{box-shadow:inset 0 0 0 9999px rgba(2, 117, 216, 0.95);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.95)}table.dataTable.table-hover>tbody>tr:hover>*{box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.075)}table.dataTable.table-hover>tbody>tr.selected:hover>*{box-shadow:inset 0 0 0 9999px rgba(2, 117, 216, 0.975);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.975)}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:auto;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:.85em}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap;justify-content:flex-end}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:1em 0}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody>table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody>table>thead .sorting:before,div.dataTables_scrollBody>table>thead .sorting_asc:before,div.dataTables_scrollBody>table>thead .sorting_desc:before,div.dataTables_scrollBody>table>thead .sorting:after,div.dataTables_scrollBody>table>thead .sorting_asc:after,div.dataTables_scrollBody>table>thead .sorting_desc:after{display:none}div.dataTables_scrollBody>table>tbody tr:first-child th,div.dataTables_scrollBody>table>tbody tr:first-child td{border-top:none}div.dataTables_scrollFoot>.dataTables_scrollFootInner{box-sizing:content-box}div.dataTables_scrollFoot>.dataTables_scrollFootInner>table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}div.dataTables_wrapper div.dataTables_paginate ul.pagination{justify-content:center !important}}table.dataTable.table-sm>thead>tr>th:not(.sorting_disabled){padding-right:20px}table.table-bordered.dataTable{border-right-width:0}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-left-width:0}table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable td:last-child,table.table-bordered.dataTable td:last-child{border-right-width:1px}table.table-bordered.dataTable tbody th,table.table-bordered.dataTable tbody td{border-bottom-width:0}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}div.table-responsive>div.dataTables_wrapper>div.row{margin:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^=col-]:first-child{padding-left:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^=col-]:last-child{padding-right:0} diff --git a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.js b/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.js deleted file mode 100644 index c99016713ab1f..0000000000000 --- a/core/src/main/resources/org/apache/spark/ui/static/dataTables.bootstrap4.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! DataTables Bootstrap 4 integration - * ©2011-2017 SpryMedia Ltd - datatables.net/license - */ -!function(t){var n,o;"function"==typeof define&&define.amd?define(["jquery","datatables.net"],function(e){return t(e,window,document)}):"object"==typeof exports?(n=require("jquery"),o=function(e,a){a.fn.dataTable||require("datatables.net")(e,a)},"undefined"==typeof window?module.exports=function(e,a){return e=e||window,a=a||n(e),o(e,a),t(a,0,e.document)}:(o(window,n),module.exports=t(n,window,window.document))):t(jQuery,window,document)}(function(x,e,n,o){"use strict";var r=x.fn.dataTable;return x.extend(!0,r.defaults,{dom:"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",renderer:"bootstrap"}),x.extend(r.ext.classes,{sWrapper:"dataTables_wrapper dt-bootstrap4",sFilterInput:"form-control form-control-sm",sLengthSelect:"custom-select custom-select-sm form-control form-control-sm",sProcessing:"dataTables_processing card",sPageButton:"paginate_button page-item"}),r.ext.renderer.pageButton.bootstrap=function(i,e,d,a,l,c){function u(e,a){for(var t,n,o=function(e){e.preventDefault(),x(e.currentTarget).hasClass("disabled")||m.page()==e.data.action||m.page(e.data.action).draw("page")},r=0,s=a.length;r",{class:b.sPageButton+" "+f,id:0===d&&"string"==typeof t?i.sTableId+"_"+t:null}).append(x("
",{href:n?null:"#","aria-controls":i.sTableId,"aria-disabled":n?"true":null,"aria-label":w[t],role:"link","aria-current":"active"===f?"page":null,"data-dt-idx":t,tabindex:n?-1:i.iTabIndex,class:"page-link"}).html(p)).appendTo(e),i.oApi._fnBindAction(n,{action:t},o))}}var p,f,t,m=new r.Api(i),b=i.oClasses,g=i.oLanguage.oPaginate,w=i.oLanguage.oAria.paginate||{};try{t=x(e).find(n.activeElement).data("dt-idx")}catch(e){}u(x(e).empty().html('