diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..05f9f62 --- /dev/null +++ b/404.html @@ -0,0 +1,3183 @@ + + + + + + + + + + + + + + + + + + + + + + + John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ +

404 - Not found

+ +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Big_Data/Hadoop_Ecosystem/index.html b/Big_Data/Hadoop_Ecosystem/index.html new file mode 100644 index 0000000..fbd8c27 --- /dev/null +++ b/Big_Data/Hadoop_Ecosystem/index.html @@ -0,0 +1,3349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Hadoop Ecosystem - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Hadoop Ecosystem

+

Hadoop is not a single product, but rather a software family. Its common components consist of the following:

+
    +
  • Pig, a scripting language used to quickly write MapReduce code to handle unstructured sources
  • +
  • Hive, used to facilitate structure for the data
  • +
  • HCatalog, used to provide inter-operatability between these internal systems
  • +
  • HBase, which is essentially a database built on top of Hadoop
  • +
  • HDFS, the actual file system for hadoop.
  • +
  • Apache Mahout
  • +
  • Packaging for Hadoop: BigTop
  • +
+

Hadoop structures data using Hive, but can handle unstructured data easily using Pig.

+

Hadoop and Mongo

+ +

AWS EMR

+

Amazon EMR Best Practices

+

Amazon EMR includes

+
    +
  • Ganglia
  • +
  • Hadoop
  • +
  • HBase
  • +
  • HCatalog
  • +
  • Hive
  • +
  • Hue
  • +
  • Mahout
  • +
  • Oozie
  • +
  • Phoenix
  • +
  • Pig
  • +
  • Prest0
  • +
  • Spark
  • +
  • Sqoop
  • +
  • Tez
  • +
  • Zeppelin
  • +
  • ZooKeeper
  • +
+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Big_Data/Install_Spark_2.3_Locally/index.html b/Big_Data/Install_Spark_2.3_Locally/index.html new file mode 100644 index 0000000..b8e8d38 --- /dev/null +++ b/Big_Data/Install_Spark_2.3_Locally/index.html @@ -0,0 +1,3398 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Install Spark 2.3 Locally - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Install Spark 2.3 Locally

+

Spark runs on Java 8+, Python 2.7+/3.4+ and R 3.1+. For the Scala API, Spark 2.3.0 uses Scala 2.11.

+

Download Spark

+

Link

+

Java

+

All you need is to have java installed on your system PATH, or the JAVA_HOME environment variable pointing to a Java installation.

+
java -version
+
+

Scala

+

Download the Scala binaries for windows -- you will need Scala 11.x (not 10.x or 12.x) for Spark 2.3

+ +

Test correct installation of scala:

+
scala -version
+
+

Set PATH for Scala if needed:

+
export PATH = $PATH:/usr/local/scala/bin
+
+

Test that Spark is properly installed:

+
./bin/spark-shell --master local[2]
+
+

On Windows, use CMD or PowerShell, not git bash

+

Error: Failure to locate the winutils binary in the hadoop binary path

+
    +
  • HADOOP_HOME (or the variable hadoop.home.dir property) needs to be set properly.
  • +
  • Known Hadoop for Windows issue: winutils is not included in the Apache distribution
  • +
+

You can fix this problem in two ways

+
    +
  • Install a full native windows Hadoop version. The ASF does not currently release such a version; releases are available externally. +Or: get the WINUTILS.EXE binary from a Hadoop redistribution. There is a repository of this for some Hadoop versions on github.
  • +
+

Then

+
    +
  • Set the environment variable %HADOOP_HOME% to point to the directory above the BIN dir containing WINUTILS.EXE.
  • +
  • Or: run the Java process with the system property hadoop.home.dir set to the home directory.
  • +
+

Explanation on Hadoop Wiki

+

Stack Overflow

+

Windows binaries for some Hadoop versions

+

Run Spark on the local machine

+

To run Spark interactively in a Python interpreter, use bin/pyspark:

+
./bin/pyspark --master local[2]
+
+

Or submit Spark jobs:

+
./bin/spark-submit examples/src/main/python/pi.py 10
+
+ +

Spark Installation Tutorial

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Big_Data/Spark_APIs/index.html b/Big_Data/Spark_APIs/index.html new file mode 100644 index 0000000..7b5e5d3 --- /dev/null +++ b/Big_Data/Spark_APIs/index.html @@ -0,0 +1,3403 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Spark APIs - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Spark APIs

+ +

DataFrames APIs

+

DataFrame operations:

+
    +
  • printSchema()
  • +
  • select()
  • +
  • show()
  • +
  • count()
  • +
  • groupBy()
  • +
  • sum()
  • +
  • limit()
  • +
  • orderBy()
  • +
  • filter()
  • +
  • withColumnRenamed()
  • +
  • join()
  • +
  • withColumn()
  • +
+

Example:

+
// In the Regular Expression below:
+// ^  - Matches beginning of line
+// .* - Matches any characters, except newline
+
+df
+ .filter($"article".rlike("""^Apache_.*"""))
+ .orderBy($"requests".desc)
+ .show() // By default, show will return 20 rows
+
+// Import the sql functions package, which includes statistical functions like sum, max, min, avg, etc.
+import org.apache.spark.sql.functions._
+
+df.groupBy("project").sum().show()
+
+

Columns

+

A new column is constructed based on the input columns present in a dataframe:

+
df("columnName")        // On a specific DataFrame.
+col("columnName")       // A generic column no yet associated with a DataFrame.
+col("columnName.field") // Extracting a struct field
+col("`a.column.with.dots`") // Escape `.` in column names.
+$"columnName"           // Scala short hand for a named column.
+expr("a + 1")           // A column that is constructed from a parsed SQL Expression.
+lit("abc")              // A column that produces a literal (constant) value.
+
+

Column objects can be composed to form complex expressions:

+
$"a" + 1
+$"a" === $"b"
+
+

File Read

+

CSV - Create a DataFrame with the anticipated structure

+
val clickstreamDF = sqlContext.read.format("com.databricks.spark.csv")
+  .option("header", "true")
+  .option("delimiter", "\\t")
+  .option("mode", "PERMISSIVE")
+  .option("inferSchema", "true")
+  .load("dbfs:///databricks-datasets/wikipedia-datasets/data-001/clickstream/raw-uncompressed")
+
+

PARQUET - To create Dataset[Row] using SparkSession

+
val people = spark.read.parquet("...")
+val department = spark.read.parquet("...")
+
+people.filter("age > 30")
+  .join(department, people("deptId") === department("id"))
+  .groupBy(department("name"), "gender")
+  .agg(avg(people("salary")), max(people("age")))
+
+

Repartitioning / Caching

+
val clickstreamNoIDs8partDF = clickstreamNoIDsDF.repartition(8)
+clickstreamNoIDs8partDF.registerTempTable("Clickstream")
+sqlContext.cacheTable("Clickstream")
+
+

An ideal partition size in Spark is about 50 MB - 200 MB. +The cache gets stored in Project Tungsten binary compressed columnar format.

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Big_Data/Spark_Basics/index.html b/Big_Data/Spark_Basics/index.html new file mode 100644 index 0000000..89d1ff5 --- /dev/null +++ b/Big_Data/Spark_Basics/index.html @@ -0,0 +1,3375 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Spark Basics - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Spark Basics

+ + + +

Spark and MongoDB

+ +

Spark and NLP

+ +

Here is a complete set of example on how to use DL4J (Deep Learning for Java) that uses UIMA on the SPARK platform

+

Deep Learning for Java

+

and in the following project the use of CTAKES UIMA module from within the Spark framework

+

Natural Language Processing with Apache Spark

+

GraphX

+ +

Apache Zeppelin

+

Connect to Zeppelin using the same SSH tunneling method to connect to other web servers on the master node. Zeppelin server is found at port 8890.

+

Zeppelin

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Big_Data/Spark_Development_with_sbt_and_InteliJ/index.html b/Big_Data/Spark_Development_with_sbt_and_InteliJ/index.html new file mode 100644 index 0000000..2a79e9e --- /dev/null +++ b/Big_Data/Spark_Development_with_sbt_and_InteliJ/index.html @@ -0,0 +1,3373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Setup a Spark Development Environment with IntelliJ and sbt - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Setup a Spark Development Environment with IntelliJ and sbt

+ +

Hortonworks tutorial

+

Packaging and Submission Steps using sbt

+

Package a jar containing your application:

+
$ sbt package
+...
+[info] Packaging {..}/{..}/target/scala-2.11/simple-project_2.11-1.0.jar
+
+

Don't use sbt run

+

Then use [spark submit] ( https://spark.apache.org/docs/latest/submitting-applications.html#launching-applications-with-spark-submit ) + to run your application

+
YOUR_SPARK_HOME/bin/spark-submit \
+  --class "SimpleApp" \
+  --master local[4] \
+  target/scala-2.11/simple-project_2.11-1.0.jar
+
+

Open the Spark UI to monitor: https://localhost:4040

+

Plugins

+

sbt-spark-package

+

The Sbt Plugin for Spark Packages is a Sbt plugin that aims to simplify the use and development of Spark Packages.

+

Blog

+

IntelliJ plugin for Spark

+

Note: does not work with IntelliJ 2018.1

+

The IntelliJ plugin for Spark supports for deployment spark application and cluster monitoring.

+
    +
  • To install, download the plugin
  • +
  • File > Settings, Plugins tab, browse repos... point to the zip file
  • +
+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Big_Data/Spark_on_AWS_EMR/index.html b/Big_Data/Spark_on_AWS_EMR/index.html new file mode 100644 index 0000000..6c2f47f --- /dev/null +++ b/Big_Data/Spark_on_AWS_EMR/index.html @@ -0,0 +1,3422 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Spark on AWS EMR - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Spark on AWS EMR

+ +

Spark on AWS EMR

+

Create a EMR Cluster with Spark using the AWS Console

+

The following procedure creates a cluster with Spark installed.

+
    +
  1. Open the Amazon EMR console at https://console.aws.amazon.com/elasticmapreduce/.
  2. +
  3. +

    Choose Create cluster to use Quick Create.

    +
  4. +
  5. +

    For the Software Configuration field, choose Amazon Release Version emr-5.0.0 or later.

    +
  6. +
  7. In the Select Applications field, choose either All Applications or Spark.
  8. +
  9. Select other options as necessary and then choose Create cluster
  10. +
+

Create a EMR Cluster with Spark using the AWS CLI

+

Simple cluster:

+
aws emr create-cluster --name "Spark cluster" --release-label emr-5.0.0 --applications Name=Spark \
+--ec2-attributes KeyName=myKey --instance-type m3.xlarge --instance-count 3 --use-default-roles
+
+

Note: For Windows, replace the above Linux line continuation character () with the caret (^).

+

When using a config file:

+
aws emr create-cluster --release-label --applications Name=Spark \
+--instance-type m3.xlarge --instance-count 3 --configurations https://s3.amazonaws.com/mybucket/myfolder/myConfig.json
+
+

Sample myConfig.json:

+
[
+  {
+    "Classification": "spark",
+    "Properties": {
+      "maximizeResourceAllocation": "true"
+    }
+  }
+]
+
+

Using Spot instances:

+
aws emr create-cluster --name "Spot cluster" --release-label emr-5.0.0 --applications Name=Spark \
+--use-default-roles --ec2-attributes KeyName=myKey \
+--instance-groups InstanceGroupType=MASTER,InstanceType=m3.xlarge,InstanceCount=1,BidPrice=0.25 \
+InstanceGroupType=CORE,BidPrice=0.03,InstanceType=m3.xlarge,InstanceCount=2
+
+# InstanceGroupType=TASK,BidPrice=0.10,InstanceType=m3.xlarge,InstanceCount=3
+
+

In Java:

+
// start Spark on EMR in java
+AmazonElasticMapReduceClient emr = new AmazonElasticMapReduceClient(credentials);
+Application sparkApp = new Application() .withName("Spark");
+Applications myApps = new Applications();
+myApps.add(sparkApp);
+RunJobFlowRequest request = new RunJobFlowRequest() .withName("Spark Cluster") .withApplications(myApps) .withReleaseLabel("") .withInstances(new JobFlowInstancesConfig() .withEc2KeyName("myKeyName") .withInstanceCount(1) .withKeepJobFlowAliveWhenNoSteps(true) .withMasterInstanceType("m3.xlarge") .withSlaveInstanceType("m3.xlarge") ); RunJobFlowResult result = emr.runJobFlow(request);
+
+

Connect to the Master Node using SSH

+

To connect to the master node using SSH, you need the public DNS name of the master node and your Amazon EC2 key pair private key. The Amazon EC2 key pair private key is specified when you launch the cluster.

+
    +
  1. To retrieve the cluster identifier / the public DNS name of the master node, type the following command:
  2. +
+
aws emr list-clusters
+
+

The output lists your clusters including the cluster IDs. Note the cluster ID for the cluster to which you are connecting.

+
"Status": {     "Timeline": {         "ReadyDateTime": 1408040782.374,         "CreationDateTime": 1408040501.213     },     "State": "WAITING",     "StateChangeReason": {         "Message": "Waiting after step completed"     } }, "NormalizedInstanceHours": 4,"Id": "j-2AL4XXXXXX5T9", "Name": "My cluster"
+
+
    +
  1. To list the cluster instances including the master public DNS name for the cluster, type one of the following commands. Replace j-2AL4XXXXXX5T9 with the cluster ID returned by the previous command.
  2. +
+
aws emr list-instances --cluster-id j-2AL4XXXXXX5T9Or:aws emr describe-clusters --cluster-id j-2AL4XXXXXX5T9
+
+

View the Web Interfaces Hosted on Amazon EMR Clusters

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Big_Data/Spark_on_EC2/index.html b/Big_Data/Spark_on_EC2/index.html new file mode 100644 index 0000000..2b18a33 --- /dev/null +++ b/Big_Data/Spark_on_EC2/index.html @@ -0,0 +1,3350 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Install Spark on EC2 with Flintrock - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Install Spark on EC2 with Flintrock

+ +

Flintrock GitHub Repo

+

Configurable CLI Defaults

+

Flintrock lets you persist your desired configuration to a YAML file so that you don't have to keep typing out the same options over and over at the command line.

+

To setup and edit the default config file, run this:

+
flintrock configure
+
+

Sample config.yaml

+
provider: ec2
+
+services:
+  spark:
+    version: 2.2.0
+
+launch:
+  num-slaves: 1
+
+providers:
+  ec2:
+    key-name: key_name
+    identity-file: /path/to/.ssh/key.pem
+    instance-type: m3.medium
+    region: us-east-1
+    ami: ami-97785bed
+    user: ec2-user
+
+

With a config file like that, you can now launch a cluster:

+
flintrock launch test-cluster
+
+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Big_Data/Spark_on_Kubernetes/index.html b/Big_Data/Spark_on_Kubernetes/index.html new file mode 100644 index 0000000..6c941f2 --- /dev/null +++ b/Big_Data/Spark_on_Kubernetes/index.html @@ -0,0 +1,3398 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Spark 2.3 on Kubernetes - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Spark 2.3 on Kubernetes

+ +

Background

+

Introduction to Spark on Kubernetes

+

Running Spark on Kubernetes

+

Main Page

+

Prerequisites:

+
    +
  • A runnable distribution of Spark 2.3 or above.
  • +
  • A running Kubernetes cluster at version >= 1.6 with access configured to it using kubectl. If you do not already have a working Kubernetes cluster, you may setup a test cluster on your local machine using minikube. +We recommend using the latest release of minikube with the DNS addon enabled.
  • +
  • Be aware that the default minikube configuration is not enough for running Spark applications. We recommend 3 CPUs and 4g of memory to be able to start a simple Spark application with a single executor.
  • +
  • You must have appropriate permissions to list, create, edit and delete pods in your cluster. You can verify that you can list these resources by running kubectl auth can-i pods. +The service account credentials used by the driver pods must be allowed to create pods, services and configmaps.
  • +
  • You must have Kubernetes DNS configured in your cluster.
  • +
+

Steps

+
    +
  • +

    Need Kubernetes version 1.6 and above. +To check the version, enter kubectl version.

    +
  • +
  • +

    The cluster must be configured to use the kube-dns addon. Check with

    +
  • +
+
minikube addons list
+
+

Kubernetes DNS Page

+
    +
  • Start minikube with the recommended configuration for Spark
  • +
+
minikube start --cpus 3 --memory 4096
+
+
    +
  • Submit a Spark job using:
  • +
+
$ bin/spark-submit \
+    --master k8s://https://<k8s-apiserver-host>:<k8s-apiserver-port> \
+    --deploy-mode cluster \
+    --name spark-pi \
+    --class org.apache.spark.examples.SparkPi \
+    --conf spark.executor.instances=3 \
+    --conf spark.kubernetes.container.image=<spark-image> \
+    local:///path/to/examples.jar
+
+

Use kubectl cluster-info to get the K8s API server URL

+

Spark (starting with version 2.3) ships with a Dockerfile in the kubernetes/dockerfiles/ directory.

+
    +
  • Access logs:
  • +
+
kubectl -n=<namespace> logs -f <driver-pod-name>
+
+
    +
  • Accessing Driver UI:
  • +
+
kubectl port-forward <driver-pod-name> 4040:4040
+
+

Then go to https://localhost:4040

+

Alternatives

+

Helm Chart for Spark

+

The same on KubeApps

+
helm install --name my-spark-release --version 0.1.12 stable/spark
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Cloud/AWS/index.html b/Cloud/AWS/index.html new file mode 100644 index 0000000..c7a43f5 --- /dev/null +++ b/Cloud/AWS/index.html @@ -0,0 +1,3514 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AWS Services Overview - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

AWS Services Overview

+

Basic Services

+
    +
  • Compute: EC2 (autoscaling, ELB load balancing)
  • +
  • Networking / Security: VPC (security groups), IAM (users/groups/application roles)
  • +
+

Storage

+
    +
  • S3: secure, scalable object-level storage, static web site hosting...
  • +
  • Glacier: long-term storage
  • +
  • EBS: block-level storage (for EC2 instances)
  • +
+

Databases

+
    +
  • RDS: relational databases (MySQL, PostgreSQL, MSSQL, MariaDB, Aurora...)
  • +
  • DynamoDB: scalable NoSQL database backed by solid-state drives
  • +
+

Analytics

+
    +
  • RedShift: PostgreSQL-based columnstore OLAP database that uses SQL. MPP architecture.
  • +
  • EMR: Hadoop cluster (Hive, Pig, HBase, Spark...).
  • +
+

ETL / ELT / Batch Processing

+
    +
  • Glue
  • +
  • Batch
  • +
  • Data Pipeline: orchestrate data transfers between S3, DynamoDB, Redshift
  • +
+

Application Services

+
    +
  • Notifications: SNS (alerts by email, SMS...), SES (bulk email)
  • +
  • Queue: SQS (async message queues for component decoupling)
  • +
  • Workflows, State Machine as a Service: AWS Step Functions, SWF (task-oriented workflows - complicated)
  • +
  • Document Search: ElasticSearch, CloudSearch
  • +
+

Monitoring

+
    +
  • Cloudwatch (monitor services and instances e.g. CPU utilization, etc...)
  • +
  • CloudTrail (monitor API calls)
  • +
+

Infrastructure Deployment / Automation

+
    +
  • Elastic Beanstalk (simple, mostly web or Linux worker)
  • +
  • CloudFormation (JSON / YAML templates - more difficult, but many existing templates)
  • +
  • OpsWork (higher level than CloudFormation, uses non-native components - Chef-based)
  • +
+

Desktop in the Cloud

+
    +
  • WorkSpaces
  • +
+

Details

+

Tools

+
    +
  • +

    Unix tools on Windows: Cygwin

    +
  • +
  • +

    Putty SSH client for Windows doc

    +
  • +
  • +

    Download and install PuTTY link. Be sure to install the entire suite.

    +
  • +
  • Start PuTTYgen (for example, from the Start menu, click All Programs > PuTTY > PuTTYgen).
  • +
  • Under Type of key to generate, select SSH-2 RSA.
  • +
  • Load the .pem file (private key) downloaded from the console (in "credentials" folder)
  • +
  • +

    Save private key

    +
  • +
  • +

    AWS command line interface

    +
  • +
  • +

    AWS toolkit for Visual Studio

    +
  • +
  • +

    AWS tools for PowerShell

    +
  • +
+

AWS EC2

+ +

login as: ec2-user (Amazon Linux) or: ubuntu

+

Bash shell documentation

+
    +
  • +

    Use a shell script to configure the instance link

    +
  • +
  • +

    User data: You can specify user data to configure an instance during launch, or to run a configuration script. To attach a file, select the "As file" option and browse for the file to attach.

    +
  • +
+

AWS S3

+

GUI tools to upload / manage files:

+
    +
  • AWS Console
  • +
  • S3 Browser
  • +
  • CloudBerry
  • +
+

Command-line s3 clients:

+
    +
  • AWS command line (see above)
  • +
  • S3 command line tools
  • +
+

Redshift

+

1) Use Case

+
    +
  • Large-scale SQL analytical database
  • +
  • Querying in Redshift is FAST
  • +
  • Full SQL compared to HiveQL
  • +
  • Redshift isn’t a complete replacement for a Hadoop system (no streaming, no text processing)
  • +
+

2) Tools

+ +

3) Get data into Redshift:

+
    +
  • COPY from S3 (delimited text files)
  • +
  • COPY from DynamoDB (NoSQL datastore)
  • +
  • JDBC/ODBC transactions (not efficient for bulk loading)
  • +
+

Tables have ‘keys’ that define how the data is split across slices. The recommended practice is to split based upon commonly-joined columns, so that joined data resides on the same slice, thus avoiding the need to move data between systems.

+

4) Examples:

+
COPY table1 FROM 's3://bucket1/' credentials 'aws_access_key_id=abc;aws_secret_access_key=xyz' delimiter '|' gzip removequotes truncatecolumns maxerror 1000
+SELECT DISTINCT field1 FROM table1
+SELECT COUNT(DISTINCT field2) FROM table1
+
+

EMR

+ +

SWF

+

The Amazon Simple Workflow Service (Amazon SWF) makes it easy to build applications that coordinate work across distributed components. In Amazon SWF, a task represents a logical unit of work that is performed by a component of your application. Coordinating tasks across the application involves managing intertask dependencies, scheduling, and concurrency in accordance with the logical flow of the application. Amazon SWF gives you full control over implementing tasks and coordinating them without worrying about underlying complexities such as tracking their progress and maintaining their state.

+

When using Amazon SWF, you implement workers to perform tasks. These workers can run either on cloud infrastructure, such as Amazon Elastic Compute Cloud (Amazon EC2), or on your own premises. You can create tasks that are long-running, or that may fail, time out, or require restarts—or that may complete with varying throughput and latency. Amazon SWF stores tasks and assigns them to workers when they are ready, tracks their progress, and maintains their state, including details on their completion. To coordinate tasks, you write a program that gets the latest state of each task from Amazon SWF and uses it to initiate subsequent tasks. Amazon SWF maintains an application's execution state durably so that the application is resilient to failures in individual components. With Amazon SWF, you can implement, deploy, scale, and modify these application components independently.

+

Amazon SWF offers capabilities to support a variety of application requirements. It is suitable for a range of use cases that require coordination of tasks, including media processing, web application back-ends, business process workflows, and analytics pipelines.

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Cloud/AWS_Lambda/index.html b/Cloud/AWS_Lambda/index.html new file mode 100644 index 0000000..f8ac8a9 --- /dev/null +++ b/Cloud/AWS_Lambda/index.html @@ -0,0 +1,3306 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AWS Lambda - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Cloud/Serverless/index.html b/Cloud/Serverless/index.html new file mode 100644 index 0000000..f66d1f4 --- /dev/null +++ b/Cloud/Serverless/index.html @@ -0,0 +1,3373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Serverless Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Serverless Cheatsheet

+

Serverless home page

+

Install

+
npm install -g serverless
+
+

Examples

+

Serverless Examples

+

Serverless Starter

+

Python example

+

C# example

+

Cheatsheet

+
    +
  • Create a Service:
  • +
+
# NodeJS
+serverless create -p [SERVICE NAME] -t aws-nodejs
+
+# C#
+serverless create --path serverlessCSharp --template aws-csharp
+
+
    +
  • Install a Service
  • +
+

This is a convenience method to install a pre-made Serverless Service locally by downloading the Github repo and unzipping it.

+
serverless install -u [GITHUB URL OF SERVICE]
+
+
    +
  • Deploy All
  • +
+

Use this when you have made changes to your Functions, Events or Resources in serverless.yml or you simply want to deploy all changes within your Service at the same time.

+
serverless deploy -s [STAGE NAME] -r [REGION NAME] -v
+
+
    +
  • Deploy Function
  • +
+

Use this to quickly overwrite your AWS Lambda code on AWS, allowing you to develop faster.

+
serverless deploy function -f [FUNCTION NAME] -s [STAGE NAME] -r [REGION NAME]
+
+
    +
  • Invoke Function
  • +
+

Invokes an AWS Lambda Function on AWS and returns logs.

+
serverless invoke -f [FUNCTION NAME] -s [STAGE NAME] -r [REGION NAME] -l
+
+
    +
  • Streaming Logs
  • +
+

Open up a separate tab in your console and stream all logs for a specific Function using this command.

+
serverless logs -f [FUNCTION NAME] -s [STAGE NAME] -r [REGION NAME]
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Containers/Debug_Kubernetes/index.html b/Containers/Debug_Kubernetes/index.html new file mode 100644 index 0000000..f84089b --- /dev/null +++ b/Containers/Debug_Kubernetes/index.html @@ -0,0 +1,3348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Debug Kubernetes - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Debug Kubernetes

+ +

Run a test Docker container

+
docker run --rm -p <port>:<port> <docker image>:<tag>
+docker ps
+# cleanup
+docker kill <container>
+
+

To override the entrypoint, use:

+
winpty docker run --rm -p <port>:<port> -it --entrypoint bash <docker image>:<tag>
+
+

The above assumes you are using cygwin / git bash on Windows.

+

Run a test K8s pod

+
kubectl run <deployment name> --image=<docker image>:<tag>
+
+

Useful options:

+
    +
  • --restart=Never
  • +
  • +

    if the pod has a console: -i --tty --command -- bash

    +
  • +
  • +

    Attach to the (first) container in the Pod:

    +
  • +
+
kubectl attach <pod name> -i -t
+
+

If there are multiple containers in the pod, use: -c <container name>

+
    +
  • Get a shell to a running Container:
  • +
+
kubectl exec -it <pod name> -- bash
+
+
    +
  • Delete test pod:
  • +
+
kubectl delete pod <pod name>
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Containers/Deploy_to_Kubernetes (Helm)/index.html b/Containers/Deploy_to_Kubernetes (Helm)/index.html new file mode 100644 index 0000000..311e101 --- /dev/null +++ b/Containers/Deploy_to_Kubernetes (Helm)/index.html @@ -0,0 +1,3507 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deploy to Kubernetes (Helm) - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Deploy to Kubernetes (Helm)

+ + +

Deploying scala sbt microservice to Kubernetes

+

SBT Native Packager - Docker

+

OpenSSL

+

Helm

+

Deployment of a sbt-built app on Kubernetes (MiniKube)

+

Test packaging without Kubernetes first

+
    +
  • Stage all Play files in a local directory and verify
  • +
+
sbt stage
+
+
    +
  • For direct deployment, create a distribution in target/universal
  • +
+
sbt dist
+
+

The dist task builds a binary version of your application that you can deploy to a server without any dependency on SBT, the only thing the server needs is a Java installation.

+

Deploy a Helm chart to Kubernetes

+

Prerequisites: minikube, kubectl, docker client and helm should be installed

+
    +
  • Generate the Dockerfile and environment prepared for creating a Docker image
  • +
+
sbt docker:stage
+
+
    +
  • +

    Verify the output under target/docker

    +
  • +
  • +

    Start minikube

    +
  • +
+
minikube start
+
+
    +
  • Enable Ingress
  • +
+
minikube addons list
+minikube addons enable ingress
+
+

Also consider enabling heapster

+
    +
  • List available nodes to verify that kubectl is properly configured
  • +
+
kubectl get nodes
+
+

It should return one node.

+
    +
  • Connect the Docker client to the Docker daemon in the K8s VM
  • +
+
eval $(minikube docker-env)
+
+

Just make sure you tag your Docker image with something other than ‘latest’ and use that tag while you pull the image. +Otherwise, if you do not specify version of your image, it will be assumed as :latest, with pull image policy of Always correspondingly, which may eventually result in ErrImagePull as you may not have any versions of your Docker image out there in the default docker registry (usually DockerHub) yet.

+
    +
  • +

    If needed, remove previously built images from the local Docker server with sbt docker:clean or docker rmi <image>. +To view the list of Docker images, run docker images

    +
  • +
  • +

    Build the Docker image and publish it to Kubernetes' Docker server.

    +
  • +
+
sbt docker:publishLocal
+
+
    +
  • Deploy the Helm chart
  • +
+
./helm install --dry-run --debug <helm chart folder> &> output.txt
+
+

and if that looks OK

+
./helm install <helm chart folder>
+
+

or specify a release name:

+
./helm install --name <release name> <helm chart folder>
+
+
    +
  • Verify the Helm deployment to minikube
  • +
+
./helm list
+./helm status <release name>
+
+

More details via:

+
kubectl get ing
+kubectl get service
+kubectl get deployment
+kubectl get pods
+
+
    +
  • Test the deployment by forwarding a local port to a port on the pod
  • +
+
kubectl get pods
+kubectl port-forward <pod name> 8080:<target port on pod>
+curl -v https://localhost:8080/api
+
+

kubectl port-forward also allows using resource name, such as a service name, to select a matching pod to port forward to

+
kubectl port-forward svc/<service name>  8080:<service port>
+curl -v https://localhost:8080/
+
+
    +
  • When needed, delete the release with
  • +
+
helm ls
+helm delete <release name>
+
+

If you want to deploy / not deploy an Ingress

+
    +
  • Update values.yaml in the Helm chart root folder
  • +
+
ingress:
+  enabled: true  # or: false; true by default
+
+
    +
  • If true, make sure the minikube Ingress add-on is enabled
  • +
+
minikube addons enable ingress
+
+
    +
  • Deploy on Kubernetes as above
  • +
+

See Blog

+

SSL Termination (TO DO)

+

IBM Ingress TLS tutorial

+
    +
  • Generate a x509, pem encoded, RSA 2048 certificate with OpenSSL
  • +
+
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${KEY_FILE} -out ${CERT_FILE} -subj "/CN=${HOST}/O=${HOST}"
+
+openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=john-cd.com"
+
+

Note: To find myhost.com for minikube, run the following commands:

+
 $ minikube ssh
+ $ echo $HOSTNAME
+ minikube
+
+
    +
  • Create a Kubernetes secret
  • +
+
kubectl create secret tls ${CERT_NAME} --key ${KEY_FILE} --cert ${CERT_FILE}
+
+kubectl create secret tls my-secret --key tls.key --cert tls.crt
+
+

Add under spec: in

+
  tls:
+  - hosts:
+    - myhost.com
+    secretName: my-secret
+
+

Find and delete all nginx pods to force the nginx.conf to update and reflect the ingress changes. Find the ingress pods with the following:

+
kubectl get pods --all-namespaces
+kubectl delete pods --namespace=kube-system [ingress pod]
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Containers/Deploy_to_Kubernetes/index.html b/Containers/Deploy_to_Kubernetes/index.html new file mode 100644 index 0000000..03cb2e5 --- /dev/null +++ b/Containers/Deploy_to_Kubernetes/index.html @@ -0,0 +1,3448 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deploy to Kubernetes - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Deploy to Kubernetes

+ +

using kubectl

+

Create ConfigMap from config files

+

A ConfigMap stores K8s-specific configuration that can be mounted as volume or used in env variables. +It is often used to provide production configuration: application configuration, log settings, etc...

+
kubectl create configmap app-conf --from-file=<path to config files>  # create a ConfigMap from multiple files in the same directory.
+
+
    +
  • Check the ConfigMap
  • +
+
kubectl get configmap app-conf -o yaml
+
+# or
+
+kubectl describe configmaps app-conf
+
+

Create a Kubernetes secret

+

You may need a Secret to store database passwords and secret keys.

+

For applications using the Play Framework, generate a secret using:

+
secretText = $(sbt playGenerateSecret)
+regex = "Generated new secret: (.+)$"
+f [[ $secretText =~ $regex ]]
+    then
+        secret = "${BASH_REMATCH[1]}"
+        echo $secret
+        kubectl create secret generic application-secret --from-literal=application_secret=$secret
+        kubectl get secrets
+    else
+        echo "$secretText doesn't match" >&2
+    fi
+done
+
+

Create Resources (Deployment, Service, Ingress, etc...)

+
kubectl create -f <path/to/resource_config.yaml>
+
+
    +
  • Verify proper resource creation
  • +
+
kubectl get ing
+kubectl get service
+kubectl get deployment
+kubectl get pods
+
+
    +
  • To delete a resource later, in this case a Deployment:
  • +
+
kubectl delete deployment <deployment name>
+
+

Install an Ingress Controller

+
    +
  • An ingress controller is necessary to make Ingresses work. See the Ingress doc
  • +
+

Minikube

+
    +
  • minikube provides its own ingress controller via the Ingress add-on:
  • +
+
minikube addons enable ingress
+
+

Enabling the add-on provisions the following:

+
    +
  • a configMap for the Nginx loadbalancer
  • +
  • the Nginx ingress controller
  • +
  • a service that exposes a default Nginx backend pod for handling unmapped requests.
  • +
+

Install the nginx ingress controller (non-minikube Kubernetes)

+ +
#./helm install stable/nginx-ingress
+
+

or with stat collection enabled for Prometheus

+
helm install --name nginx-ingress-release stable/nginx-ingress \
+  --set controller.stats.enabled=true \
+  --set controller.metrics.enabled=true
+
+
    +
  • Verify that the Ingress exists
  • +
+
kubectl get ing
+
+

See explanations and documentation

+

The nginx ingress controller requires a 404-server like this

+

Alternative ingress controllers

+ + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Containers/Docker/index.html b/Containers/Docker/index.html new file mode 100644 index 0000000..03918e1 --- /dev/null +++ b/Containers/Docker/index.html @@ -0,0 +1,3460 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Docker Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Docker Cheatsheet

+ +

Docker Cheat Sheet

+

Docker Documentation

+

Docker Tutorials and Labs

+

Docker + Jenkins

+

Docker Hub

+

Concepts

+

A Docker image is a read-only template. For example, an image could contain an Ubuntu operating system with Apache and your web application installed. Images are used to create Docker containers. Docker provides a simple way to build new images or update existing images, or you can download Docker images that other people have already created. Docker images are the buildcomponent of Docker.

+

Docker registries hold images.

+

Cheatsheet

+

To show only running containers use:

+
docker ps
+
+

To show all containers use:

+
docker ps -a
+
+

Show last started container:

+
docker ps -l
+
+

Download an image:

+
docker pull centos
+
+

Create then start a container: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] + * Docker run reference

+
docker run hello-world
+
+

Run with interactive terminal (i = interactive t = terminal):

+
docker run -it ubuntu bash
+
+

Start then detach the container (daemonize):

+
docker run -d -p8088:80 --name webserver nginx
+
+

If you want a transient container, docker run --rm will remove the container after it stops.

+

Looks inside the container (use -f to act like tail -f):

+
docker logs <container name>
+
+

Stop container:

+
docker stop <container name>   # container ID or name
+
+

Delete container:

+
docker rm <container name>
+
+

To check the environment:

+
docker run -it alpine env
+
+

Docker version / info:

+
docker version
+docker info
+
+

Port Mapping

+

-p 80:5000 would map port 80 on our local host to port 5000 inside our container.

+
docker run -d -p 80:5000 training/webapp python app.py
+
+

Full format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort

+
docker run -d -p 127.0.0.1:80:5000 training/webapp python app.py
+
+

Both hostPort and containerPort can be specified as a range of ports. When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range, for example: -p1234-1236:1234-1236/tcp

+

The -P flag tells Docker to map any required network ports inside our container to our host (using random ports).

+
docker run -d -P training/webapp python app.py
+
+

Linking

+

--link <name or id>:alias where name is the name of the container we’re linking to and alias is an alias for the link name. +The --link flag also takes the form: --link <name or id>

+
docker run -d --name myES -p 9200:9200 -p 9300:9300 elasticsearch
+docker run --name myK --link myES:elasticsearch  -p 5601:5601 -d docker-kibana-sense
+
+

Networks

+
docker network ls
+
+

Find out the container’s IP address:

+
docker network inspect bridge
+
+

Data Volumes

+

Create a new volume inside a container at /webapp:

+
docker run -d -P --name web -v /webapp training/webapp python app.py
+docker inspect web
+
+

You can also use the VOLUME instruction in a Dockerfile to add one or more new volumes to any container created from that image.

+

Mount the host directory, /src/webapp, into the container at /opt/webapp.

+
docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
+
+

On Windows, use: docker run -v /c/Users/<path>:/<container path> ...

+

Example Dockerfile

+
vim Dockerfile
+
+
FROM docker/whalesay:latest
+RUN apt-get -y update && apt-get install -y fortunes
+CMD /usr/games/fortune -a | cowsay
+
+
docker build -t docker-whale .
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Containers/Helm_Chart_Creation/index.html b/Containers/Helm_Chart_Creation/index.html new file mode 100644 index 0000000..c5c076d --- /dev/null +++ b/Containers/Helm_Chart_Creation/index.html @@ -0,0 +1,3344 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Helm Chart Creation - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Helm Chart Creation

+ + +

How to create your first Helm chart

+

Steps

+
./helm create <folder containing chart>
+
+./helm lint <folder>
+
+./helm install --dry-run --debug <folder>
+
+

To create dependencies between charts

+

Create requirements.yaml

+

Add a remote repo

+
./helm repo add stable https://kubernetes-charts.storage.googleapis.com
+
+

and, from the chart directory, run:

+
../helm dependency update
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Containers/Kubernetes_Cheatsheet/index.html b/Containers/Kubernetes_Cheatsheet/index.html new file mode 100644 index 0000000..0e0859c --- /dev/null +++ b/Containers/Kubernetes_Cheatsheet/index.html @@ -0,0 +1,3355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kubernetes Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Kubernetes Cheatsheet

+ +

minikube

+
    +
  • To access the Kubernetes Dashboard, run this command in a shell after starting Minikube to get the address:
  • +
+
minikube dashboard
+
+
    +
  • The minikube VM is exposed to the host system via a host-only IP address, that can be obtained with the minikube ip command
  • +
+

kubectl

+

kubectl Cheat Sheet

+
    +
  • Run a particular image on the cluster (creates a deployment automatically)
  • +
+
kubectl run hello-world --replicas=2 --labels="run=load-balancer-example" --image=gcr.io/google-samples/node-hello:1.0  --port=8080
+
+
    +
  • kubectl get - list resources.
  • +
  • kubectl get deployment to get all deployments
  • +
  • kubectl get pods -l app=nginx to get pods with label "app: nginx"
  • +
  • kubectl describe - show detailed information about a resource
  • +
  • kubectl logs - print the logs from a container in a pod
  • +
  • kubectl exec - execute a command on a container in a pod
  • +
+

Using the Docker daemon in the Minikube VM

+

When using a single VM of Kubernetes, it’s really handy to reuse the minikube’s built-in Docker daemon

+
eval $(minikube docker-env)
+# test with
+docker ps
+
+

Just make sure you tag your Docker image with something other than ‘latest’ and use that tag while you pull the image. +Otherwise, if you do not specify version of your image, it will be assumed as :latest, with pull image policy of Always correspondingly, which may eventually result in ErrImagePull as you may not have any versions of your Docker image out there in the default docker registry (usually DockerHub) yet.

+

A Docker client is required to publish built docker images to the Docker daemon running inside of minikube. +See installing Docker for instructions for your platform.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Containers/Kubernetes_Concepts/index.html b/Containers/Kubernetes_Concepts/index.html new file mode 100644 index 0000000..15fdcff --- /dev/null +++ b/Containers/Kubernetes_Concepts/index.html @@ -0,0 +1,3288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kubernetes Concepts - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Kubernetes Concepts

+ +
    +
  • Pods - A Pod is a Kubernetes abstraction that represents a group of one or more application containers (such as Docker or rkt), and some shared resources for those containers. +Kubernetes workloads, such as Deployments and Jobs, are composed of one or more Pods. +Shared pod resources include:
  • +
  • Shared storage, as Volumes
  • +
  • Networking, as a unique cluster IP address
  • +
  • +

    Information about how to run each container, such as the container image version or specific ports to use

    +
  • +
  • +

    Nodes: A Pod always runs on a Node. A Node is a worker machine in Kubernetes and may be either a virtual or a physical machine, depending on the cluster. Each Node is managed by the Master. A Node can have multiple pods, and the Kubernetes master automatically handles scheduling the pods across the Nodes in the cluster.

    +
  • +
  • +

    Deployment - The most common way of running X copies (Pods) of your application. Supports rolling updates to your container images.

    +
  • +
  • +

    Service - By itself, a Deployment can’t receive traffic. Setting up a Service is one of the simplest ways to configure a Deployment to receive and loadbalance requests. Depending on the type of Service used, these requests can come from external client apps or be limited to apps within the same cluster. A Service is tied to a specific Deployment using label selection.

    +
  • +
  • +

    Labels - Identifying metadata that you can use to sort and select sets of API objects. Labels have many applications, including the following:

    +
  • +
  • +

    To keep the right number of replicas (Pods) running in a Deployment. The specified label is used to stamp the Deployment’s newly created Pods (as the value of the spec.template.labels configuration field), and to query which Pods it already manages (as the value of spec.selector.matchLabels).

    +
  • +
  • To tie a Service to a Deployment using the selector field.
  • +
  • To look for specific subset of Kubernetes objects, when you are using kubectl. For instance, the command kubectl get deployments --selector=app=nginx only displays Deployments from the nginx app.
  • +
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Containers/Kubernetes_Examples/index.html b/Containers/Kubernetes_Examples/index.html new file mode 100644 index 0000000..fe229c6 --- /dev/null +++ b/Containers/Kubernetes_Examples/index.html @@ -0,0 +1,3395 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Kubernetes Examples - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Kubernetes Examples

+ +

Service + Deployment example

+
apiVersion: v1
+kind: Service
+metadata:
+  name: p2p-robot-service
+spec:
+  selector:
+    app: p2p-robot
+  ports:
+  - name: http
+    protocol: TCP
+    port: 80
+    targetPort: http    # can a text label (port name) or port number
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: p2p-robot-deployment
+spec:
+  selector:
+    matchLabels:
+      app: p2p-robot
+  replicas: 2          # tells deployment to run 2 pods matching the template
+  template:            # create pods using pod definition in this template
+    metadata:
+      # the name is not included in the meta data as a unique name is
+      # generated from the deployment name
+      labels:
+        app: p2p-robot # label used above in matchLabels
+    spec:
+        containers:
+        - name: p2p-robot
+          image: "johncd/p2p-robot:1.0.0"
+          imagePullPolicy: IfNotPresent
+          ports:
+          - containerPort: 9000
+            name: http
+          env:
+          - name: APPLICATION_SECRET    #  Place the application secret in an environment variable, which is read in application.conf 
+            valueFrom:
+                secretKeyRef:
+                  name: application-secret
+                  key: application_secret           
+          volumeMounts:
+          - name: conf-volume
+            mountPath: /usr/local/etc
+        volumes:
+        - name: conf-volume
+          configMap:            # The configMap resource provides a way to inject configuration data into Pods.
+            name: app-conf
+
+

Ingress example

+
# Ingress 
+# https://kubernetes.io/docs/concepts/services-networking/ingress/
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+  name: test
+  annotations:
+    ingress.kubernetes.io/rewrite-target: /
+    kubernetes.io/ingress.class: nginx      # Use the nginx-ingress Ingress controller
+spec:
+  tls:
+  - secretName: ingresssecret  # Referencing this secret in an Ingress will tell the Ingress controller to secure the channel from the client to the loadbalancer using TLS
+  rules:
+  - http:
+      paths:
+      - path: /api
+        backend:
+          serviceName: s1
+          servicePort: 80
+---
+# Secure the Ingress by specifying a secret that contains a TLS private key and certificate. 
+apiVersion: v1
+data:
+  tls.crt: base64 encoded cert
+  tls.key: base64 encoded key
+kind: Secret
+metadata:
+  name: ingresssecret
+  namespace: default
+type: Opaque
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Containers/Minikube_Install_in_Ubuntu_on_Windows/index.html b/Containers/Minikube_Install_in_Ubuntu_on_Windows/index.html new file mode 100644 index 0000000..541d452 --- /dev/null +++ b/Containers/Minikube_Install_in_Ubuntu_on_Windows/index.html @@ -0,0 +1,3328 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Minikube Install in Ubuntu on Windows - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Minikube Install in Ubuntu on Windows

+ +

Install kubectl in Ubuntu on Windows

+
cd ~
+mkdir bin
+curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
+chmod +x ./kubectl
+# optionally
+sudo mv ./kubectl /usr/local/bin/kubectl
+# then test
+kubectl get all
+# enable autocompletion
+source <(kubectl completion bash)
+echo "source <(kubectl completion bash)" >> ~/.bashrc
+
+
    +
  • If necessary, install socat
  • +
+
sudo apt-get update && sudo apt-get install socat
+
+
    +
  • In order for kubectl to find and access a Kubernetes cluster, it needs a kubeconfig file, which is created automatically when you create a cluster using kube-up.sh or successfully deploy a Minikube cluster.
  • +
+

Check that kubectl is properly configured by getting the cluster state:

+
kubectl cluster-info
+
+

Beware that you may have two different config files in ~/.kube/ and /mnt/c/Users/<user name>/.kube if you installed minikube in Windows.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Containers/Minikube_Install_on_Windows/index.html b/Containers/Minikube_Install_on_Windows/index.html new file mode 100644 index 0000000..1331808 --- /dev/null +++ b/Containers/Minikube_Install_on_Windows/index.html @@ -0,0 +1,3483 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Minikube Install on Windows - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Minikube Install on Windows

+ +

Install minikube on Windows

+

Minikube runs a single-node Kubernetes cluster inside a VM on your laptop for users looking to try out Kubernetes or develop with it day-to-day.

+
    +
  • For Windows, install VirtualBox or Hyper-V first.
  • +
  • Minikube is distributed in binary form: GitHub Repo. Download the minikube-installer.exe file, and execute the installer. This should automatically add minikube.exe to your path with an uninstaller available as well.
  • +
  • If needed, add C:\Program Files (x86)\Kubernetes\minikube or similar to the PATH (in System Settings > Environment Variables)
  • +
  • Test that minikube works:
  • +
+
minikube
+
+

More info at Getting Started

+

Install kubectl

+

Use a version of kubectl that is the same version as your server or later. Using an older kubectl with a newer server might produce validation errors.

+

On Windows 10 (using Git Bash):

+
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/windows/amd64/kubectl.exe
+
+

OR

+

Install Choco

+

Then

+
choco install kubernetes-cli
+
+

Run kubectl version to verify that the version you’ve installed is sufficiently up-to-date.

+
kubectl version
+
+

Configure kubectl

+

Configure kubectl to use a remote Kubernetes cluster

+
    +
  • If ~/.kube config does not exist (it should have been created by minikube), enter the following in Powershell:
  • +
+
cd C:\users\<yourusername>
+mkdir .kube
+cd .kube
+New-Item config -type file
+
+
    +
  • +

    Edit the config file with a text editor of your choice.

    +
  • +
  • +

    Check that kubectl is properly configured by getting the cluster state:

    +
  • +
+
kubectl cluster-info
+
+
    +
  • Enable auto-completion (if you use Git Bash)
  • +
+
echo "source <(kubectl completion bash)" >> ~/.bashrc
+
+
    +
  • You must have appropriate permissions to list, create, edit and delete pods in your cluster:
  • +
+
kubectl auth can-i list pods
+kubectl auth can-i create pods
+kubectl auth can-i edit pods
+kubectl auth can-i delete pods
+
+

Run kubectl from the Ubuntu on Windows command line

+

If installed by choco

+
export PATH=$PATH:/mnt/c/ProgramData/chocolatey/bin/kubectl
+
+# then use:
+kubectl.exe
+
+

Run minikube

+

Running Kubernetes Locally via Minikube

+ +
choco install curl
+
+
    +
  • Test curl
  • +
+
curl https://google.com
+
+
    +
  • Start minikube
  • +
+
minikube start
+
+
    +
  • List hosts
  • +
+
kubectl get nodes
+
+
    +
  • Test by deploying a container (creates a deployment / pod automatically)
  • +
+
kubectl run hello-minikube --image=k8s.gcr.io/echoserver:1.4 --port=8080
+
+
    +
  • Provide a dynamic port to the container (creates a service automatically)
  • +
+
kubectl expose deployment hello-minikube --type=NodePort
+
+

We have now launched an echoserver pod but we have to wait until the pod is up before curling/accessing it via the exposed service. +To check whether the pod is up and running we can use the following:

+
kubectl get pod
+
+

Once the pod is running, curl it:

+
curl $(minikube service hello-minikube --url)
+
+
    +
  • Cleanup:
  • +
+
kubectl delete deployment hello-minikube
+
+
kubectl delete service hello-minikube
+
+
minikube stop
+
+

Install Helm

+

Helm is a package manager for Kubernetes. Download a binary release of the Helm client from here

+
    +
  • Once you have Helm ready, you can initialize the local CLI and also install Tiller into your Kubernetes cluster in one step:
  • +
+
helm init
+
+

This will install Tiller (the helm server) into the current Kubernetes cluster (as listed in kubectl config current-context).

+
    +
  • Install a test Helm chart, then clean up
  • +
+
helm repo update              # Make sure we get the latest list of charts
+helm install stable/mysql
+helm ls
+helm status <release name>
+helm delete <release name>
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Data_Science/Data_Manipulation/index.html b/Data_Science/Data_Manipulation/index.html new file mode 100644 index 0000000..6d6b665 --- /dev/null +++ b/Data_Science/Data_Manipulation/index.html @@ -0,0 +1,3324 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Data Manipulation - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Data Manipulation

+ +

Pandas

+ +

Data Wrangling with .NET

+

Quora: Which is the best machine learning library for .NET?

+

Deedle- Exploratory data library for .NET

+

Deedle is an easy to use library for data and time series manipulation and for scientific programming. It supports working with structured data frames, ordered and unordered data, as well as time series. Deedle is designed to work well for exploratory programming using F# and C# interactive console, but can be also used in efficient compiled .NET code.

+

The library implements a wide range of operations for data manipulation including advanced indexing and slicing, joining and aligning data, handling of missing values, grouping and aggregation, statistics and more.

+

Accord.NET Framework

+

Accord.NET provides statistical analysis, machine learning, image processing and computer vision methods for .NET applications. The Accord.NET Framework extends the popular AForge.NET with new features, adding to a more complete environment for scientific computing in .NET.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Data_Science/Data_Visualization/index.html b/Data_Science/Data_Visualization/index.html new file mode 100644 index 0000000..06f16c0 --- /dev/null +++ b/Data_Science/Data_Visualization/index.html @@ -0,0 +1,3361 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Data Visualization - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Data Visualization

+ +

Basics

+

Data visualization - Wikipedia

+

19 Tools for Data Visualization Projects

+

22 free tools for data visualization and analysis - Computerworld

+

22 free tools for data visualization and analysis

+

JavaScript libraries / APIs

+

D3.js - Data-Driven Documents

+

D3 provides many built-in reusable functions and function factories, such as graphical primitives for area, line and pie charts.

+

D3 building blocks

+

C3.js

+

Google Charts

+

Tools

+

plot.ly

+

Tableau

+

Qlik

+

Quadrigram

+

Open-source data viz

+

Superset vs Metabase vs ReDash

+

AirPal

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Data_Science/Deep_Learning/index.html b/Data_Science/Deep_Learning/index.html new file mode 100644 index 0000000..6679d2b --- /dev/null +++ b/Data_Science/Deep_Learning/index.html @@ -0,0 +1,3335 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Libraries - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + + + + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Data_Science/Dimensionality_Reduction/index.html b/Data_Science/Dimensionality_Reduction/index.html new file mode 100644 index 0000000..87c80a4 --- /dev/null +++ b/Data_Science/Dimensionality_Reduction/index.html @@ -0,0 +1,3307 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dimensionality Reduction - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + + + + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Data_Science/Keras/index.html b/Data_Science/Keras/index.html new file mode 100644 index 0000000..1ba370e --- /dev/null +++ b/Data_Science/Keras/index.html @@ -0,0 +1,3282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Keras Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + + + + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Data_Science/Machine_Learning/index.html b/Data_Science/Machine_Learning/index.html new file mode 100644 index 0000000..ab51b93 --- /dev/null +++ b/Data_Science/Machine_Learning/index.html @@ -0,0 +1,3429 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Machine Learning - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Useful Links

+

DataTau

+

Datasets

+ +

Algorithms

+

Restricted Boltzmann Machines

+

A Beginner's Tutorial for Restricted Boltzmann Machines - Deeplearning4j- Open-source, Distributed Deep Learning for the JVM

+

Embedding

+

t-distributed stochastic neighbor embedding - Wikipedia

+

Reinforcement Learning

+

Lecture 10 Reinforcement Learning I

+

PyBrain

+

PyBrain - a simple neural networks library in Python

+

CyBrain

+

ML Plaforms

+

Palladium

+

GUI tools

+
    +
  • Orange
  • +
  • Provides a design tool for visual programming allowing you to connect together data preparation, algorithms, and result evaluation +together to create machine learning “programs”. Provides over 100 widgets for the environment and also provides a Python API and library for +integrating into your application.
  • +
  • Weka explorer
  • +
  • A graphical machine learning workbench. It provides an explorer that you can use to prepare data, run algorithms and review results. It +also provides an experimenter where you can perform the same tasks in a controlled environment and design a batch of algorithm runs that could +run for an extended period of time and then review the results. Finally, it also provides a data flow interface where you can plug algorithms +together like a flow diagram. Under the covers you can use Weka as a Java library and write programs that make use of the algorithms.
  • +
  • BigML
  • +
  • A web service where you can upload your data, prepare it and run algorithms on it. It provides clean and easy to use interfaces for +configuring algorithms (decision trees) and reviewing the results. The best feature of this service is that it is all in the cloud, meaning that +all you need is a web browser to get started. It also provides an API so that if you like it you can build an application around it.
  • +
+

Tutorials

+ +

Books

+ + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Data_Science/Recommenders/index.html b/Data_Science/Recommenders/index.html new file mode 100644 index 0000000..93606de --- /dev/null +++ b/Data_Science/Recommenders/index.html @@ -0,0 +1,3307 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Recommender Systems - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Data_Science/scikit-learn/index.html b/Data_Science/scikit-learn/index.html new file mode 100644 index 0000000..1b4c885 --- /dev/null +++ b/Data_Science/scikit-learn/index.html @@ -0,0 +1,3305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scikit-Learn - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Databases/Mongodb/index.html b/Databases/Mongodb/index.html new file mode 100644 index 0000000..801beb1 --- /dev/null +++ b/Databases/Mongodb/index.html @@ -0,0 +1,3466 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MongoDB Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

MongoDB Cheatsheet

+ +

Import from CSV

+
mongoimport --db users --collection contacts --type csv --headerline --file contacts.csv
+
+

Specifying --headerline instructs mongoimport to determine the name of the fields using the first line in the CSV file. +Use the --ignoreBlanks option to ignore blank fields. For CSV and TSV imports, this option provides the desired functionality in most cases, because it avoids inserting fields with null values into your collection.

+

MongoImport documentation

+ +
myCursor.forEach(printjson);
+
+// or
+while (myCollection.hasNext()) {
+   printjson(myCollection.next());
+}
+
+

Aggregation Tips

+
// lowercase a string
+{ $project: { "address": { $toLower: "$address" } } },
+
+// extract field within embedded document
+{ $project: { "experience.location": 1 } },
+
+// flatten
+{ $unwind: "$experience"},
+{ $group: { _id: "$_id", locs: { $push: { $ifNull: [ "$experience.location", "undefined" ] } } } }
+
+// output a collection
+{ $out: "myCollection2" }
+
+// get unique values
+{ $group: { _id: "$fulladdress" } }
+
+

Make a Copy

+

Don't use copyTo - it is fully blocking... and deprecated in 3.x

+
    +
  • Use the Aggregation framework:
  • +
+
db = db.getSiblingDB("myDB"); // set current db for $out
+var myCollection = db.getCollection("myCollection");
+
+// project if needed, get uniques if needed, create a new collection
+myCollection.aggregate([{ $project:{ "fulladdress": 1 } },{ $group:{ _id: "$fulladdress" } },{ $out: "outputCollection" }], { allowDiskUse:true });
+
+
    +
  • Or use bulk update:
  • +
+
var outputColl = db.getCollection( "outputCollection" );
+var outputBulk = outputColl.initializeUnorderedBulkOp();
+myCollection.find( {}, { "fulladdress": 1 } ).forEach( function(doc) {
+     outputBulk.insert(doc);
+});
+outputBulk.execute();
+
+

Longer Example

+

Add a count field to all records

+
function gatherStats() {
+    var start = Date.now();
+
+    var inputDB = db.getSiblingDB("inputDB");
+    var inputColl = inputDB.getCollection("inputColl");
+
+    // debug: inputColl.find( {} ).limit(2).forEach(printjson);
+
+    outputDB = db.getSiblingDB("outputDB");
+    db = outputDB; // set current database for the next aggregate step
+
+    // create temporary collection with count
+    inputColl.aggregate(  [
+    { $group: { _id: { $toLower: "$address" }, count: { $sum: 1 } } },
+    { $sort: { "count": -1 } },
+    { $limit: 100000 },                 // limit to 100k addresses with highest count
+    { $out: "stats" }
+    ],  { allowDiskUse: true } );       // returns { _id, count } where _id is the address
+
+    var statsColl = outputDB.getCollection("stats");
+
+   // create output collection
+    var outputColl = outputDB.getCollection("outputColl");
+    var outputBulk = outputColl.initializeUnorderedBulkOp();
+    var counter = 0;
+
+    var inputCursor = inputColl.find( {}, {} );
+    inputCursor.forEach( function(doc) {
+        var statDoc = statsColl.findOne( { _id: doc.address } );
+        if (statDoc) {
+            doc.count = statDoc.count;
+            outputBulk.insert(doc);
+            counter++;
+            if ( counter % 1000 == 0 ) {
+                    outputBulk.execute();
+                    // you have to reset
+                    outputBulk = outputColl.initializeUnorderedBulkOp();
+                }
+            }
+        }
+    );
+
+    if ( counter % 1000 > 0 )
+        outputBulk.execute();
+
+
+    // print the results
+    outputColl.find({}).sort({count: -1}).forEach(printjson);
+
+    var end = Date.now();
+    var duration = (end - start)/1000;
+    printjson("Duration: " + duration + " seconds");
+
+    printjson(" | DONE | ");
+}
+
+gatherStats();
+
+

Alternatively move data to memory:

+
    var statsDict = {}; // or better Object.create(null);
+    statsColl.find({}).forEach( function(doc) { statsDict[doc._id] = doc.count } );
+
+    // could also use: var statsArray = statsCursor.toArray();
+
+    inputCursor.forEach( function(doc) {
+        if (doc.address in statsDict)
+        {
+            doc["count"] = statsDict[doc.address];
+            outputBulk.insert(doc);
+        }
+    });
+    outputBulk.execute();
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Databases/Redshift/index.html b/Databases/Redshift/index.html new file mode 100644 index 0000000..f9e80f1 --- /dev/null +++ b/Databases/Redshift/index.html @@ -0,0 +1,3329 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RedShift - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

RedShift

+ +

Redshift Best Practices

+
    +
  • Smaller node types load data faster
  • +
  • Best Practices for data load:
  • +
  • 1 file in S3 per slice (instances in RedShift)
  • +
  • Compressed using gzip compression
  • +
  • File size: 1MB to 1GB compressed
  • +
  • COPY from S3 is the fastest
  • +
  • COPY from EMR HDFS may be faster, but most people don't use HDFS - they store data in S3
  • +
  • +

    First column of SORTKEY should not be compressed

    +
  • +
  • +

    Workflows: move from staging table to production table

    +
  • +
  • Make sure to wrap the entire workflow into ONE transaction
  • +
  • COMMITs are very expensive in RedShift
  • +
  • Disable statistics on staging tables
  • +
  • Make sure that the distribution keys match between staging and prod tables
  • +
  • +

    Compress your staging tables

    +
  • +
  • +

    Do ANALYZE after VACUUM

    +
  • +
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Databases/SQL/index.html b/Databases/SQL/index.html new file mode 100644 index 0000000..e418a8e --- /dev/null +++ b/Databases/SQL/index.html @@ -0,0 +1,4175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SQL Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

SQL Cheatsheet

+

DML: SELECT

+

Filter:

+
SELECT LastName, FirstName, Address FROM Persons
+WHERE Address IS NULL
+
+

Like:

+
SELECT * FROM Customers
+WHERE City LIKE 's%';
+
+SELECT * FROM Customers
+WHERE Country LIKE '%land%';
+
+SELECT * FROM Customers
+WHERE Country NOT LIKE '%land%';
+
+

Sort:

+
SELECT * FROM Customers
+ORDER BY Country DESC;
+
+SELECT * FROM Customers
+ORDER BY Country, CustomerName;
+
+

Limit:

+
SELECT TOP number|percent column_name(s)
+FROM table_name;
+
+-- Examples:
+SELECT TOP 2 * FROM Customers;
+
+SELECT TOP 50 PERCENT * FROM Customers;
+
+

Oracle Syntax:

+
SELECT column_name(s)
+FROM table_name
+WHERE ROWNUM <= number;
+
+

Joins:

+
SELECT Customers.CustomerName, Orders.OrderID
+FROM Customers
+FULL OUTER JOIN Orders
+ON Customers.CustomerID = Orders.CustomerID
+ORDER BY Customers.CustomerName;
+
+

Union:

+
SELECT column_name(s) FROM table1
+UNION
+SELECT column_name(s) FROM table2;
+
+SELECT column_name(s) FROM table1
+UNION ALL
+SELECT column_name(s) FROM table2;
+
+

Select Into:

+
SELECT column_name(s)
+INTO newtable [IN externaldb]
+FROM table1;
+
+

Formula:

+
SELECT ProductName, UnitPrice*(UnitsInStock+ISNULL(UnitsOnOrder,0))
+FROM Products
+
+

DML: INSERT

+
INSERT INTO table_name
+VALUES (value1,value2,value3,...);
+
+INSERT INTO table_name (column1,column2,column3,...)
+VALUES (value1,value2,value3,...);
+
+-- Example:
+
+INSERT INTO Customers (CustomerName, City, Country)
+VALUES ('Cardinal', 'Stavanger', 'Norway');
+
+

Insert from select:

+
INSERT INTO table2(column_name(s))
+SELECT column_name(s)
+FROM table1;
+
+-- Example:
+
+INSERT INTO Customers (CustomerName, Country)
+SELECT SupplierName, Country FROM Suppliers
+WHERE Country='Germany';
+
+

DML: UPDATE

+
UPDATE table_name
+SET column1=value1,column2=value2,...
+WHERE some_column=some_value;
+
+-- Example:
+
+UPDATE Customers
+SET ContactName='Alfred Schmidt', City='Hamburg'
+WHERE CustomerName='Alfreds Futterkiste';
+
+

DML: DELETE

+
DELETE FROM table_name
+WHERE some_column=some_value;
+
+DELETE FROM Customers
+WHERE CustomerName='Alfreds Futterkiste' AND ContactName='Maria Anders';
+
+

Databases

+
CREATE DATABASE my_db;
+
+DROP DATABASE my_db;
+
+

Tables

+

Create:

+
CREATE TABLE table_name
+(
+column_name1 data_type(size),
+column_name2 data_type(size),
+column_name3 data_type(size),
+....
+);
+
+CREATE TABLE table_name
+(
+column_name1 data_type(size) constraint_name,
+column_name2 data_type(size) constraint_name,
+column_name3 data_type(size) constraint_name,
+....
+);
+
+

-- Examples

+
CREATE TABLE Persons
+(
+P_Id int NOT NULL UNIQUE,
+LastName varchar(255) NOT NULL,
+FirstName varchar(255),
+Address varchar(255),
+City varchar(255)
+)
+
+CREATE TABLE Persons
+(
+P_Id int NOT NULL,
+LastName varchar(255) NOT NULL,
+FirstName varchar(255),
+Address varchar(255),
+City varchar(255),
+CONSTRAINT uc_PersonID UNIQUE (P_Id, LastName)
+)
+
+
ALTER TABLE Persons
+ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)
+
+ALTER TABLE Persons
+DROP CONSTRAINT uc_PersonID
+
+

Temporary Table:

+
CREATE TABLE #MyTempTable (cola INT PRIMARY KEY);
+INSERT INTO #MyTempTable VALUES (1);
+
+

Drop / Truncate:

+
DROP TABLE table_name
+
+TRUNCATE TABLE table_name
+
+

PRIMARY KEY constraint

+
CREATE TABLE Persons
+(
+P_Id int NOT NULL PRIMARY KEY,
+LastName varchar(255) NOT NULL,
+FirstName varchar(255),
+Address varchar(255),
+City varchar(255)
+)
+
+CREATE TABLE Persons
+(
+P_Id int NOT NULL,
+LastName varchar(255) NOT NULL,
+FirstName varchar(255),
+Address varchar(255),
+City varchar(255),
+CONSTRAINT PK_PersonID PRIMARY KEY (P_Id,LastName)
+)
+
+ALTER TABLE Persons
+ADD CONSTRAINT PK_PersonID PRIMARY KEY (P_Id,LastName)
+
+ALTER TABLE Persons
+DROP CONSTRAINT PK_PersonID
+
+

FOREIGN KEY constraints

+
CREATE TABLE Orders
+(
+O_Id int NOT NULL PRIMARY KEY,
+OrderNo int NOT NULL,
+P_Id int FOREIGN KEY REFERENCES Persons(P_Id)
+)
+
+CREATE TABLE Orders
+(
+O_Id int NOT NULL,
+OrderNo int NOT NULL,
+P_Id int,
+PRIMARY KEY (O_Id),
+CONSTRAINT FK_PerOrders FOREIGN KEY (P_Id)
+REFERENCES Persons(P_Id)
+)
+
+
ALTER TABLE Orders
+ADD FOREIGN KEY (P_Id)
+REFERENCES Persons(P_Id)
+
+ALTER TABLE Orders
+ADD CONSTRAINT fk_PerOrders
+FOREIGN KEY (P_Id)
+REFERENCES Persons(P_Id)
+
+ALTER TABLE Orders
+DROP CONSTRAINT fk_PerOrders
+
+

CHECK Constraints

+
CREATE TABLE Persons
+(
+P_Id int NOT NULL CHECK (P_Id>0),
+LastName varchar(255) NOT NULL,
+FirstName varchar(255),
+Address varchar(255),
+City varchar(255)
+)
+
+CREATE TABLE Persons
+(
+P_Id int NOT NULL,
+LastName varchar(255) NOT NULL,
+FirstName varchar(255),
+Address varchar(255),
+City varchar(255),
+CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes')
+)
+
+
ALTER TABLE Persons
+ADD CONSTRAINT CHK_Person CHECK (P_Id>0 AND City='Sandnes')
+
+ALTER TABLE Persons
+DROP CONSTRAINT CHK_Person
+
+

DEFAULT Constraints

+
CREATE TABLE Orders
+(
+O_Id int NOT NULL,
+OrderNo int NOT NULL,
+P_Id int,
+OrderDate date DEFAULT GETDATE()
+)
+
+
ALTER TABLE Persons
+ALTER COLUMN City SET DEFAULT 'SEATTLE'
+
+ALTER TABLE Persons
+ALTER COLUMN City DROP DEFAULT
+
+

Index

+
CREATE UNIQUE INDEX index_name
+ON table_name (column_name)
+
+CREATE INDEX index_name
+ON table_name (column_name1, col_name2)
+
+-- Example:
+
+CREATE INDEX PIndex
+ON Persons (LastName, FirstName)
+
+
DROP INDEX table_name.index_name
+
+-- Example:
+
+DROP INDEX IX_ProductVendor_BusinessEntityID
+    ON Purchasing.ProductVendor;
+
+

Add / drop / alter column in table

+
ALTER TABLE table_name
+ADD column_name datatype
+
+ALTER TABLE table_name
+DROP COLUMN column_name
+
+ALTER TABLE table_name
+ALTER COLUMN column_name datatype
+
+

Autoincrement

+
CREATE TABLE Persons
+(
+ID int IDENTITY(1,1) PRIMARY KEY,
+LastName varchar(255) NOT NULL,
+FirstName varchar(255),
+Address varchar(255),
+City varchar(255)
+)
+
+

Example:

+
CREATE TABLE dbo.PurchaseOrderDetail
+(
+    PurchaseOrderID int NOT NULL
+        REFERENCES Purchasing.PurchaseOrderHeader(PurchaseOrderID),
+    LineNumber smallint NOT NULL,
+    ProductID int NULL
+        REFERENCES Production.Product(ProductID),
+    UnitPrice money NULL,
+    OrderQty smallint NULL,
+    ReceivedQty float NULL,
+    RejectedQty float NULL,
+    DueDate datetime NULL,
+    rowguid uniqueidentifier ROWGUIDCOL  NOT NULL
+        CONSTRAINT DF_PurchaseOrderDetail_rowguid DEFAULT (newid()),
+    ModifiedDate datetime NOT NULL
+        CONSTRAINT DF_PurchaseOrderDetail_ModifiedDate DEFAULT (getdate()),
+    LineTotal  AS ((UnitPrice*OrderQty)),
+    StockedQty  AS ((ReceivedQty-RejectedQty)),
+    CONSTRAINT PK_PurchaseOrderDetail_PurchaseOrderID_LineNumber
+              PRIMARY KEY CLUSTERED (PurchaseOrderID, LineNumber)
+              WITH (IGNORE_DUP_KEY = OFF)
+)
+ON PRIMARY;
+
+

Views

+
CREATE VIEW view_name AS
+SELECT column_name(s)
+FROM table_name
+WHERE condition
+
+
CREATE OR REPLACE VIEW view_name AS
+SELECT column_name(s)
+FROM table_name
+WHERE condition
+
+
DROP VIEW view_name
+
+

Examples:

+
CREATE VIEW [Products Above Average Price] AS
+SELECT ProductName,UnitPrice
+FROM Products
+WHERE UnitPrice > (SELECT AVG(UnitPrice) FROM Products)
+
+SELECT * FROM [Products Above Average Price]
+
+
CREATE VIEW [Category Sales For 1997] AS
+SELECT DISTINCT CategoryName, Sum(ProductSales) AS CategorySales
+FROM [Product Sales for 1997]
+GROUP BY CategoryName
+
+

Dates

+
GETDATE()  -- Returns the current date and time
+
+DATEPART() -- Returns a single part of a date/time
+
+DATEADD()  -- Adds or subtracts a specified time interval from a date
+
+DATEDIFF() -- Returns the time between two dates
+
+CONVERT()  -- Displays date/time data in different formats
+
+

Example:

+
CREATE TABLE Orders
+(
+OrderId int NOT NULL PRIMARY KEY,
+ProductName varchar(50) NOT NULL,
+OrderDate datetime NOT NULL DEFAULT GETDATE()
+)
+
+SELECT DATEPART(yyyy,OrderDate) AS OrderYear,
+DATEPART(mm,OrderDate) AS OrderMonth,
+DATEPART(dd,OrderDate) AS OrderDay,
+FROM Orders
+WHERE OrderId=1
+
+SELECT OrderId,DATEADD(day,45,OrderDate) AS OrderPayDate
+FROM Orders
+
+SELECT DATEDIFF(day,'2008-06-05','2008-08-05') AS DiffDate
+
+CONVERT(VARCHAR(19),GETDATE())
+CONVERT(VARCHAR(10),GETDATE(),10)
+CONVERT(VARCHAR(10),GETDATE(),110)
+
+

SQL Server Data Types

+

Data type / Description / Storage

+

char(n) +Fixed width character string. Maximum 8,000 characters +Defined width

+

varchar(n) +Variable width character string. Maximum 8,000 characters +2 bytes + number of chars

+

varchar(max) +Variable width character string. Maximum 1,073,741,824 characters +2 bytes + number of chars

+

text +Variable width character string. Maximum 2GB of text data +4 bytes + number of chars

+

nchar +Fixed width Unicode string. Maximum 4,000 characters +Defined width x 2

+

nvarchar +Variable width Unicode string. Maximum 4,000 characters

+

nvarchar(max) +Variable width Unicode string. Maximum 536,870,912 characters

+

ntext +Variable width Unicode string. Maximum 2GB of text data

+

bit +Allows 0, 1, or NULL

+

binary(n) +Fixed width binary string. Maximum 8,000 bytes

+

varbinary +Variable width binary string. Maximum 8,000 bytes

+

varbinary(max) +Variable width binary string. Maximum 2GB

+

image +Variable width binary string. Maximum 2GB

+

Number types

+

tinyint +Allows whole numbers from 0 to 255 +1 byte

+

smallint +Allows whole numbers between -32,768 and 32,767 +2 bytes

+

int +Allows whole numbers between -2,147,483,648 and 2,147,483,647 +4 bytes

+

bigint +Allows whole numbers between -9,223,372,036,854,775,808 and 9,223,372,036,854,775,807 +8 bytes

+

decimal(p,s) +Fixed precision and scale numbers. +Allows numbers from -10^38 +1 to 10^38.

+

The p parameter indicates the maximum total number of digits that can be stored (both to the left and to the right of the decimal point). p must be a value from 1 to 38. Default is 18. The s parameter indicates the maximum number of digits stored to the right of the decimal point. s must be a value from 0 to p. Default value is 0. +5-17 bytes

+

numeric(p,s) +Fixed precision and scale numbers. +Allows numbers from -10^38 +1 to 10^38.

+

The p parameter indicates the maximum total number of digits that can be stored (both to the left and to the right of the decimal point). p must be a value from 1 to 38. Default is 18. The s parameter indicates the maximum number of digits stored to the right of the decimal point. s must be a value from 0 to p. Default value is 0. +5-17 bytes

+

smallmoney +Monetary data from -214,748.3648 to 214,748.3647 +4 bytes

+

money +Monetary data from -922,337,203,685,477.5808 to 922,337,203,685,477.5807 +8 bytes

+

float(n) +Floating precision number data from -1.79E + 308 to 1.79E + 308. +The n parameter indicates whether the field should hold 4 or 8 bytes. float(24) holds a 4-byte field and float(53) holds an 8-byte field. Default value of n is 53. +4 or 8 bytes

+

real +Floating precision number data from -3.40E + 38 to 3.40E + 38 +4 bytes

+

Date types

+

datetime +From January 1, 1753 to December 31, 9999 with an accuracy of 3.33 milliseconds +8 bytes

+

datetime2 +From January 1, 0001 to December 31, 9999 with an accuracy of 100 nanoseconds +6-8 bytes

+

smalldatetime +From January 1, 1900 to June 6, 2079 with an accuracy of 1 minute +4 bytes

+

date +Store a date only. From January 1, 0001 to December 31, 9999 +3 bytes

+

time +Store a time only to an accuracy of 100 nanoseconds +3-5 bytes

+

datetimeoffset +The same as datetime2 with the addition of a time zone offset +8-10 bytes

+

timestamp +Stores a unique number that gets updated every time a row gets created or modified. The timestamp value is based upon an internal clock and does not correspond to real time. Each table may have only one timestamp variable

+

Other data types

+

sql_variant +Stores up to 8,000 bytes of data of various data types, except text, ntext, and timestamp

+

uniqueidentifier +Stores a globally unique identifier (GUID)

+

xml +Stores XML formatted data. Maximum 2GB

+

cursor +Stores a reference to a cursor used for database operations

+

table +Stores a result-set for later processing

+

SQL Aggregate Functions

+

SQL aggregate functions return a single value, calculated from values in a column.

+

Useful aggregate functions:

+
    +
  • AVG() - Returns the average value
  • +
  • COUNT() - Returns the number of rows
  • +
  • TOP 1 - Single sample
  • +
  • MAX() - Returns the largest value
  • +
  • MIN() - Returns the smallest value
  • +
  • SUM() - Returns the sum
  • +
+

Examples:

+
SELECT COUNT(DISTINCT column_name) FROM table_name;
+
+SELECT TOP 1 column_name FROM table_name
+ORDER BY column_name DESC;
+
+SELECT column_name, aggregate_function(column_name)
+FROM table_name
+WHERE column_name operator value
+GROUP BY column_name;
+
+SELECT Shippers.ShipperName, COUNT(Orders.OrderID) AS NumberOfOrders
+FROM Orders
+LEFT JOIN Shippers
+ON Orders.ShipperID=Shippers.ShipperID
+GROUP BY ShipperName;
+
+SELECT column_name, aggregate_function(column_name)
+FROM table_name
+WHERE column_name operator value
+GROUP BY column_name
+HAVING aggregate_function(column_name) operator value;
+
+SELECT Employees.LastName, COUNT(Orders.OrderID) AS NumberOfOrders
+FROM Orders
+INNER JOIN Employees
+ON Orders.EmployeeID=Employees.EmployeeID)
+GROUP BY LastName
+HAVING COUNT(Orders.OrderID) > 10;
+
+

SQL Scalar functions

+
    +
  • Converts a field to upper case: SELECT UPPER(column_name) FROM table_name;
  • +
  • Converts a field to lower case: SELECT LOWER(column_name) FROM table_name;
  • +
  • MID() - Extract characters from a text field
  • +
  • LEN() - Returns the length of a text field
  • +
  • ROUND() - Rounds a numeric field to the number of decimals specified
  • +
  • NOW() - Returns the current system date and time
  • +
  • FORMAT() - Formats how a field is to be displayed
  • +
+
SELECT ProductName, ROUND(Price,0) AS RoundedPrice
+FROM Products;
+
+

Variables

+
DECLARE @myvar char(20);
+SET @myvar = 'This is a test';
+SELECT @myvar;
+
+

Scalar Function

+
CREATE FUNCTION FunctionName
+(
+-- Add the parameters for the function here
+@p1 int
+)
+RETURNS int
+AS
+BEGIN
+-- Declare the return variable here
+DECLARE @Result int
+-- Add the T-SQL statements to compute the return value here
+SELECT @Result = @p1
+
+-- Return the result of the function
+RETURN @Result
+END
+
+

Table Value Function

+
IF OBJECT_ID (N'dbo.EmployeeByID' ) IS NOT NULL
+   DROP FUNCTION dbo.EmployeeByID
+GO
+
+CREATE FUNCTION dbo.EmployeeByID(@InEmpID int)
+RETURNS @retFindReports TABLE
+(
+    -- columns returned by the function
+    EmployeeID int NOT NULL,
+    Name nvarchar(255 ) NOT NULL,
+    Title nvarchar(50 ) NOT NULL,
+    EmployeeLevel int NOT NULL
+)
+AS
+-- body of the function
+BEGIN
+   WITH DirectReports(Name , Title , EmployeeID , EmployeeLevel , Sort ) AS
+    (SELECT CONVERT( varchar(255 ), c .FirstName + ' ' + c.LastName ),
+        e.Title ,
+        e.EmployeeID ,
+        1 ,
+        CONVERT(varchar (255), c. FirstName + ' ' + c .LastName)
+     FROM HumanResources.Employee AS e
+          JOIN Person.Contact AS c ON e.ContactID = c.ContactID
+     WHERE e.EmployeeID = @InEmpID
+   UNION ALL
+     SELECT CONVERT (varchar( 255), REPLICATE ( '| ' , EmployeeLevel) +
+        c.FirstName + ' ' + c. LastName),
+        e.Title ,
+        e.EmployeeID ,
+        EmployeeLevel + 1,
+        CONVERT ( varchar(255 ), RTRIM (Sort) + '| ' + FirstName + ' ' +
+                 LastName)
+     FROM HumanResources.Employee as e
+          JOIN Person.Contact AS c ON e.ContactID = c.ContactID
+          JOIN DirectReports AS d ON e. ManagerID = d. EmployeeID
+    )
+   -- copy the required columns to the result of the function
+
+   INSERT @retFindReports
+   SELECT EmployeeID, Name, Title, EmployeeLevel
+     FROM DirectReports
+   ORDER BY Sort
+   RETURN
+END
+GO
+
+

Stored Procedure

+
CREATE PROCEDURE ProcedureName
+        -- Add the parameters for the stored procedure here
+        @p1 int = 0 ,
+        @p2 int = 0
+AS
+BEGIN
+        -- SET NOCOUNT ON added to prevent extra result sets from
+        -- interfering with SELECT statements.
+        SET NOCOUNT ON;
+
+    -- Insert statements for procedure here
+        SELECT @p1 , @p2
+END
+GO
+
+

Self-join

+

Q. Here's the data in a table 'orders'

+
customer_id order_id order_day
+123        27424624    25Dec2011
+123        89690900    25Dec2010
+797        12131323    25Dec2010
+876        67145419    15Dec2011
+
+

Could you give me SQL for customers who placed orders on both the days, 25th Dec 2010 and 25th Dec 2011?

+
    SELECT o.customer_id, o.order_day
+    FROM orders AS o
+    INNER JOIN orders AS o1
+    ON o.customer_id = o1.customer_id
+    WHERE ...
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/DevOps/CloudFormation/index.html b/DevOps/CloudFormation/index.html new file mode 100644 index 0000000..7eb5e82 --- /dev/null +++ b/DevOps/CloudFormation/index.html @@ -0,0 +1,3527 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CloudFormation Basics - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

CloudFormation Basics

+ +

DevOps Philosophy

+

Why we use Terraform and not Chef, Puppet, Ansible, SaltStack, or CloudFormation

+

Tools

+ +

YAML

+ +

YAML notation for folded text: >

+
data: >
+   Wrapped text
+   will be folded
+   into a single
+   paragraph
+
+   Blank lines denote
+   paragraph breaks
+
+

Sample Templates

+

Templates for the US East (Northern Virginia) Region

+

AWSlabs on GitHub

+ +

Cloudonaut Templates

+

Free Templates for AWS CloudFormation (Cloudonaut)

+

Deploying Microservices with Amazon ECS, AWS CloudFormation, and an Application Load Balancer

+

Template Basics

+

Template Basics

+

Template Anatomy

+
---
+AWSTemplateFormatVersion: "version date"
+
+Description:
+  String
+
+Metadata:
+  template metadata
+
+Parameters:
+  set of parameters
+
+Mappings:
+  set of mappings
+
+Conditions:
+  set of conditions
+
+Transform:
+  set of transforms
+
+Resources:
+  set of resources
+
+Outputs:
+  set of outputs
+
+

With examples:

+
---
+AWSTemplateFormatVersion: "2010-09-09"
+
+Description: >
+  Here are some
+  details about
+  the template.
+
+Metadata:
+  Instances:
+    Description: "Information about the instances"
+  Databases:
+    Description: "Information about the databases"
+
+Parameters:
+  InstanceTypeParameter:
+    Type: String            # String, Number, List<Number>, CommaDelimitedList e.g. "test,dev,prod", or an AWS-specific types such as Amazon EC2 key pair names and VPC IDs.
+    Default: t2.micro
+    AllowedValues:
+      - t2.micro
+      - m1.small
+    Description: Enter t2.micro or m1.small. Default is t2.micro.
+    # AllowedPattern: "[A-Za-z0-9]+" # A regular expression that represents the patterns you want to allow for String types.
+    # ConstraintDescription: Malformed input-Parameter MyParameter must match pattern [A-Za-z0-9]+
+    # MinLength: 2  # for String
+    # MaxLength: 10
+    # MinValue: 0   # for Number types.
+    # MaxValue: 100
+    # NoEcho: True
+
+Mappings:
+  RegionMap:
+    us-east-1:
+      "32": "ami-6411e20d"
+    us-west-1:
+      "32": "ami-c9c7978c"
+    eu-west-1:
+      "32": "ami-37c2f643"
+    ap-southeast-1:
+      "32": "ami-66f28c34"
+    ap-northeast-1:
+      "32": "ami-9c03a89d"
+
+Conditions:
+  CreateProdResources: !Equals [ !Ref EnvType, prod ]
+
+Transform:
+  set of transforms
+
+Resources:
+  Ec2Instance:
+      Type: AWS::EC2::Instance
+      Properties:
+        InstanceType:
+          Ref: InstanceTypeParameter  # reference to parameter above
+        ImageId: ami-2f726546
+
+Outputs:
+  VolumeId:
+    Condition: CreateProdResources
+    Value:
+      !Ref NewVolume
+
+
    +
  • The Ref function can refer to input parameters that are specified at stack creation time.
  • +
+

Examples

+

S3

+
Resources:
+  HelloBucket:
+    Type: AWS::S3::Bucket  # AWS::ProductIdentifier::ResourceType
+
+

EC2

+
Resources:
+  Ec2Instance:
+    Type: AWS::EC2::Instance
+    Properties:
+      SecurityGroups:
+      - Ref: InstanceSecurityGroup
+      KeyName: mykey
+      ImageId: ''
+  InstanceSecurityGroup:
+    Type: AWS::EC2::SecurityGroup
+    Properties:
+      GroupDescription: Enable SSH access via port 22
+      SecurityGroupIngress:
+      - IpProtocol: tcp
+        FromPort: '22'
+        ToPort: '22'
+        CidrIp: 0.0.0.0/0
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/DevOps/Git/index.html b/DevOps/Git/index.html new file mode 100644 index 0000000..aaac210 --- /dev/null +++ b/DevOps/Git/index.html @@ -0,0 +1,3620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Git Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Git Cheatsheets

+ +

Repo hosting:

+ +

Common Commands

+
    +
  • Create a new Git repository in current directory:
  • +
+
git init
+
+
    +
  • Or create an empty Git repository in the specified directory:
  • +
+
git init <directory>
+
+
    +
  • Or copy an existing Git repository:
  • +
+
git clone <repo URL>
+
+
    +
  • Clone the repository located at <repo> into the folder called <directory> on the local machine:
  • +
+
git clone <repo> <directory>
+git clone username@host:/path/to/repository
+
+
    +
  • Global Configuration:
  • +
+
git config --global user.name "Firstname Lastname"
+git config --global user.email "your_email@youremail.com"
+
+
    +
  • Stage all changes in <file> for the next commit:
  • +
+
git add <file>
+
+
    +
  • Or stage all changes in <directory> for the next commit:
  • +
+
git add <directory>  # usually '.' for current directory
+
+
    +
  • Commit the staged snapshot to the project history:
  • +
+
git commit  # interactive
+git commit -m "<message>"
+
+
    +
  • Or add and commit all in one:
  • +
+
git commit -am "message"
+
+
    +
  • Fix up the most recent commit (don't do that if shared history):
  • +
+
git commit --amend
+
+
    +
  • List which files are staged, unstaged, and untracked:
  • +
+
git status
+git status -s  # short format
+
+
    +
  • Show file diff:
  • +
+
git diff           #  git diff by itself doesn’t show all changes made since your last commit – only changes that are still unstaged.
+git diff --staged  #  Shows file differences between staging and the last file version
+
+
    +
  • Open GUI:
  • +
+
git gui
+
+
    +
  • Displays committed snapshots:
  • +
+
git log -n <limit>
+git log --graph --decorate --oneline
+
+
    +
  • Checking out commits, and checking out branches:
  • +
+
git checkout <commit>       #  Return to commit
+git checkout master         #  Return to the master branch (or whatever branch we choose)
+
+
    +
  • Check out a previous version of a file:
  • +
+
git checkout <commit> <file>    #  Check out the version of the file from the selected commit
+git checkout HEAD hello.py      #  Check out the most recent version
+
+

Branches

+

Branches are just pointers to commits.

+
    +
  • List all of the branches in your repository. Also tell you what branch you're currently in ('*' branch):
  • +
+
git branch
+
+
    +
  • Create a new branch called <branch>.
  • +
+
git branch <branch>
+
+

This does not check out the new branch. You need:

+
git checkout <existing-branch>
+
+

Or direcly create-and-check out <new-branch>.

+
git checkout -b <new-branch>
+
+
    +
  • Safe delete the branch:
  • +
+
git branch -d <branch>
+
+
    +
  • Merge the specified branch into the current branch:
  • +
+
git merge <branch>
+
+
    +
  • Undo any undesired changes
  • +
+

Generate a new commit that undoes all of the changes introduced in <commit>, then apply it to the current branch

+
git revert <commit>
+
+

git revert undoes a single commit — it does not “revert” back to the previous state of a project by removing all subsequent commits.

+
    +
  • Reset (dangerous method - erases history):
  • +
+
git reset
+
+
    +
  • List the remote connections you have to other repositories.
  • +
+
git remote -v
+
+
    +
  • Create a new connection / delete a connection to a remote repository.
  • +
+
git remote add <name> <url>  # often "origin"
+git remote rm <name>         # delete
+
+
    +
  • Fetch the specified remote’s copy of the current branch and immediately merge it into the local copy. This is the same as git fetch <remote> followed by git merge origin/<current-branch>.
  • +
+
git pull <remote>
+
+
    +
  • Put my changes on top of what everybody else has done. Ensure a linear history by preventing unnecessary merge commits.
  • +
+
git pull --rebase <remote>
+
+
    +
  • Transfer commits from your local repository to a remote repo.
  • +
+
git push <remote> <branch>
+
+
    +
  • Pushes the current branch to the remote server and links the local branch to the remote so next time you can do git pull or git push.
  • +
+
git push -u origin <branch>
+
+

Typical Workflows

+

Clone a Repo

+
mkdir repos
+cd ~/repos
+git clone https://<url>
+ls -al  <repo dir>
+
+

Add a change in the working directory to the staging area

+
git status
+git add README
+
+

-A, --all finds new files as well as staging modified content and removing files that are no longer in the working tree.

+
git add -A
+git commit -m "Add repo instructions"
+git push -u origin master
+git pull
+ssh -p 2222 user@domain.com
+
+

Short-lived topic branches

+
    +
  • Start a new feature:
  • +
+
git checkout -b new-feature master
+
+
    +
  • Edit some files:
  • +
+
git add <file>
+git commit -m "Start a feature"
+
+
    +
  • Edit some files
  • +
+
git add <file>
+git commit -m "Finish a feature"
+
+
    +
  • Merge in the new-feature branch
  • +
+
git checkout master
+git merge new-feature
+git branch -d new-feature
+
+

Push and pull from a centralized repo

+
    +
  • To push the master branch to the central repo:
  • +
+
git push origin master
+
+

If local history has diverged from the central repository, Git will refuse the request.

+
git pull --rebase origin master
+
+

Sync my local repo with the remote repo

+
git pull origin master
+git add filename.xyz
+git commit . -m “comment”
+git push origin master
+
+

Create a central Repo

+

The --bare flag creates a repository that doesn’t have a working directory, making it impossible to edit files and commit changes in that repository. Central repositories should always be created as bare repositories because pushing branches to a non-bare repository has the potential to overwrite changes.

+
git init --bare foobar.git
+git rev-parse --show-toplevel     # print top-level directory
+git rev-parse --git-dir           # print .git directory name
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/DevOps/Orchestrator_Scheduler/index.html b/DevOps/Orchestrator_Scheduler/index.html new file mode 100644 index 0000000..dfeb479 --- /dev/null +++ b/DevOps/Orchestrator_Scheduler/index.html @@ -0,0 +1,3326 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Orchestrators / Schedulers - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Java/Gradle/index.html b/Java/Gradle/index.html new file mode 100644 index 0000000..6093675 --- /dev/null +++ b/Java/Gradle/index.html @@ -0,0 +1,3538 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Gradle Basics - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Gradle

+

Install

+

In Windows 10 WSL, install sdkman

+
sudo apt install zip
+curl -s "https://get.sdkman.io" | bash
+source "$HOME/.sdkman/bin/sdkman-init.sh"
+sdk version
+
+

Install gradle

+
sdk install gradle
+gradle -v
+
+

Create a gradle project (for Java)

+
cd /mnt/d/code/gradle
+gradle init --type java-application  
+
+

You can now use ./gradlew or gradlew.bat in the project folder

+

Usage with Java

+

Example for the JVM

+

Common commands

+
    +
  • ./gradlew tasks in your project directory lists which tasks you can run in your project, such as building or running your code.
  • +
  • ./gradlew projects
  • +
  • ./gradlew properties
  • +
+

Most commonly used Java tasks:

+
    +
  • ./gradlew build will compile your project's code into a /build folder.
  • +
  • ./gradlew run will run the compiled code in your build folder.
  • +
  • ./gradlew clean will purge that build folder.
  • +
  • ./gradlew test will execute unit tests without building or running your code again.
  • +
+

Build process

+
    +
  • Gradle launches as a new JVM process
  • +
  • It parses the gradle.properties file and configures Gradle accordingly
  • +
  • Next, it creates a Settings instance for the build
  • +
  • Then, it evaluates the settings.gradle file against the Settings object
  • +
  • It creates a hierarchy of Projects, based on the configured Settings object
  • +
  • Finally, it executes each build.gradle file against its project
  • +
+

In case of a multi-project build, we'd probably have multiple different build.gradle files, one for each project. +The build.gradle file is executed against a Project instance, with one Project instance created per subproject.

+

Groovy DSL

+

Every Gradle build is made up of one or more projects. What a project represents depends on what it is that you are doing with Gradle. For example, a project might represent a library JAR or a web application.

+

Each project is made up of one or more tasks. A task represents some atomic piece of work which a build performs. This might be compiling some classes, creating a JAR, generating Javadoc, or publishing some archives to a repository.

+

Tasks

+

Tasks are snippets that we can run directly from the command line in our project directory via ./gradlew [TASK_NAME]

+
./gradlew copy
+
+
task copy(type: Copy, group: "Custom", description: "Copies sources to the dest directory") {
+    from "src"
+    into "dest"
+}
+
+// accessing task properties
+println copy.destinationDir
+println project.copy.destinationDir
+
+
task('copy2', type: Copy) {
+    description 'Copies the resource directory to the target directory.'
+    from(file('src'))
+    into(buildDir)
+    include('**/*.txt', '**/*.xml', '**/*.properties')
+    timeout = Duration.ofMillis(50000)
+}
+
+
task hello {
+    group = 'Worthless tasks'
+    description = 'An utterly useless task'
+    // extra (custom) properties
+    ext.myProperty = "myValue"
+    doLast {
+        println 'Hello world!'
+    }
+}
+
+// API call
+hello.doLast {
+    println "Greetings from the $hello.name task."  // accessing task property in interpolated string
+}
+
+hello.configure {
+    doLast {
+        println 'Hello again'
+    }
+}
+
+task next {
+    dependsOn hello   // or 'hello' if lazy initialized - task dependency 
+    doLast {
+       println hello.myProperty
+    }
+}
+
+
./gradlew -q hello
+./gradlew -q next
+
+
// dynamic tasks
+4.times { counter ->
+    task "task$counter" {
+        doLast {
+            println "I'm task number $counter"
+        }
+    }
+}
+
+// default tasks
+defaultTasks 'task0', 'task1'
+
+
import org.apache.commons.codec.binary.Base64
+
+// dependencies for the build script
+buildscript {
+    repositories {
+        mavenCentral()
+    }
+    dependencies {
+        classpath group: 'commons-codec', name: 'commons-codec', version: '1.2'
+    }
+}
+
+task encode {
+    doLast {
+        // using the build script dependencies
+        def byte[] encodedString = new Base64().encode('hello world\n'.getBytes())
+        println new String(encodedString)
+    }
+}
+
+// you can also declare methods
+File[] fileList(String dir) {
+    file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()
+}
+
+

Plugins

+

https://plugins.gradle.org/

+
plugins {
+    id "base"
+}
+
+

Essential plugins for Java:

+
plugins {
+    id 'java'
+    id 'application'
+}
+
+apply plugin:'application'
+
+

Dependencies and repositories

+
repositories {
+    jcenter()  // or mavenCentral()
+}
+
+dependencies {
+    implementation 'com.google.guava:guava:26.0-jre'  // implementation is a configuration defined by the java plugin
+    compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.13'
+
+    testImplementation 'junit:junit:4.12'
+}
+
+// pointer to the Java entrypoint
+mainClassName="com.someorg.someprj.App"
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Java/Java/index.html b/Java/Java/index.html new file mode 100644 index 0000000..821132b --- /dev/null +++ b/Java/Java/index.html @@ -0,0 +1,3357 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Java Pointers - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Java Pointers

+ +

Install Java

+

JDK download

+
java -version
+
+

Java Tools

+

List 1

+

List 2

+ +

Java Libraries

+

Libraries

+ + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Java/Log4j/index.html b/Java/Log4j/index.html new file mode 100644 index 0000000..365d1f9 --- /dev/null +++ b/Java/Log4j/index.html @@ -0,0 +1,3427 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Apache Log4j 2 - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Apache Log4j 2

+

Log4j quick guide

+

Key Components

+
    +
  • loggers: Responsible for capturing logging information.
  • +
  • appenders: Responsible for publishing logging information to various preferred destinations.
  • +
  • layouts: Responsible for formatting logging information in different styles.
  • +
+

There are seven levels of logging defined within the API: OFF, DEBUG, INFO, ERROR, WARN, FATAL, and ALL.

+

Install

+

Download Log4j

+
$ gunzip apache-log4j-1.2.15.tar.gz
+$ tar -xvf apache-log4j-1.2.15.tar
+$ pwd
+/usr/local/apache-log4j-1.2.15
+$ export CLASSPATH=$CLASSPATH:/usr/local/apache-log4j-1.2.15/log4j-1.2.15.jar
+$ export PATH=$PATH:/usr/local/apache-log4j-1.2.15/
+
+

Maven Snippet

+
<dependencies>
+<dependency>
+<groupId>org.apache.logging.log4j</groupId>
+<artifactId>log4j-api</artifactId>
+<version>2.6.1</version>
+</dependency>
+<dependency>
+<groupId>org.apache.logging.log4j</groupId>
+<artifactId>log4j-core</artifactId>
+<version>2.6.1</version>
+</dependency>
+</dependencies>
+
+

log4j.properties

+

All the libraries should be available in CLASSPATH and yourlog4j.properties file should be available in PATH.

+
# Define the root logger with appender file
+log = /usr/home/log4j
+log4j.rootLogger = WARN, FILE
+
+# Define the file appender
+log4j.appender.FILE=org.apache.log4j.FileAppender
+log4j.appender.FILE.File=${log}/log.out
+
+# Define the layout for file appender
+log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
+log4j.appender.FILE.layout.conversionPattern=%m%n
+
+

Snippets

+
import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class MyTest {
+
+ private static final Logger logger = LogManager.getLogger(); // equiv to  LogManager.getLogger(MyTest.class);
+ private static final Logger logger = LogManager.getLogger("HelloWorld");
+
+ public static void main(String[] args) {
+      logger.setLevel(Level.WARN);
+      logger.info("Hello, World!");
+      // string interpolation
+      logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());
+
+      // pre-Java 8 style optimization: explicitly check the log level
+      // to make sure the expensiveOperation() method is only called if necessary
+      if (logger.isTraceEnabled()) {
+  logger.trace("Some long-running operation returned {}", expensiveOperation());
+      }
+
+      // Java-8 style optimization: no need to explicitly check the log level:
+      // the lambda expression is not evaluated if the TRACE level is not enabledlogger.trace("Some long-running operation returned {}", () -> expensiveOperation());
+      }
+}
+
+// FORMATTER LOGGER
+public static Logger logger = LogManager.getFormatterLogger("Foo");
+
+logger.debug("Logging in user %s with birthday %s", user.getName(), user.getBirthdayCalendar());
+logger.debug("Logging in user %1$s with birthday %2$tm %2$te,%2$tY", user.getName(), user.getBirthdayCalendar());
+//
+logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Java/Maven/index.html b/Java/Maven/index.html new file mode 100644 index 0000000..5e1b364 --- /dev/null +++ b/Java/Maven/index.html @@ -0,0 +1,3450 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Maven - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Maven

+ + +

https://maven.apache.org/

+

Maven Cheatsheet

+

Maven Quick Ref

+

Apache-maven-2

+

Maven Basics

+

Maven Download / Install

+

Nexus

+

Basics

+
    +
  • Install:
  • +
+
cd /usr/local
+ln -s apache-maven-3.0.5 maven
+export PATH=/usr/local/maven/bin:$PATH
+mvn -v
+
+
    +
  • Settings file:
  • +
+
~/.m2/settings.xml
+
+

It contains user-specific configuration for authentication, repositories, and other information to customize the behavior of Maven.

+
    +
  • Maven Repo:
  • +
+
~/.m2/repository/
+
+

This directory contains your local Maven repository. When you download a dependency from a remote Maven repository, Maven stores a copy of the dependency in your local repository.

+

Directory Layout

+

Introduction to the standard directory layout

+

Without customization, source code is assumed to be in ${basedir}/src/main/java and resources are assumed to be in ${basedir}/src/main/resources. +Tests are assumed to be in ${basedir}/src/test, and a project is assumed to produce a JAR file. +Maven assumes that you want the compile bytecode to ${basedir}/target/classes and then create a distributable JAR file in ${basedir}/target

+

For WAR files, the /WEB-INF directory contains a file named web.xml which defines the structure of the web application. +See also Tomcat Deployment guide

+

Cheatsheet

+
    +
  • Bring up a menu of choices
  • +
+
mvn archetype:generate -DgroupId=com.dw -DartifactId=es-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
+
+
    +
  • Create a Java project
  • +
+
mvn archetype:create -DgroupId=org.yourcompany.project -DartifactId=application
+
+
    +
  • Create a web project
  • +
+
mvn archetype:create -DgroupId=org.yourcompany.project -DartifactId=application -DarchetypeArtifactId=maven-archetype-webapp
+
+
    +
  • Clean project (will delete target directory)
  • +
+
mvn clean
+
+
    +
  • Validate project (validate the project is correct and all necessary information is available)
  • +
+
mvn validate
+
+
    +
  • Compile project (compile source code, classes stored in target/classes)
  • +
+
mvn compile
+
+
    +
  • Test project (run tests using a suitable unit testing framework)
  • +
+
mvn test
+
+
    +
  • Package project (take the compiled code and package it in its distributable format, such as a JAR / WAR)
  • +
+
mvn package
+
+
    +
  • Verify project (run any checks to verify the package is valid and meets quality criteria)
  • +
+
mvn verify
+
+
    +
  • Install project (install the package into the local repository, for use as a dependency in other projects locally)
  • +
+
mvn install
+mvn clean install -DskipTests -Dmaven.javadoc.skip=true
+
+
    +
  • Deploy project (done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects)
  • +
+
mvn deploy
+
+
    +
  • Deploy-file (can be used for deploying a external jar file to repository)
  • +
+
mvn deploy:deploy-file -Dfile=/path/to/jar/file -DrepositoryId=repos-server -Durl=http ://repos.company.o
+
+

You can run mvn site and then find an index.html file in target/site that contains links to JavaDoc and a few reports about your source code.

+

POM files

+

Use the search engine at repository.sonatype.org to find dependencies by name and get the xml necessary to paste into your pom.xml

+
<project>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.sonatype.mavenbook</groupId>
+  <artifactId>my-project</artifactId>
+  <version>1.0-SNAPSHOT</version>
+</project>
+
+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Java/Spring/index.html b/Java/Spring/index.html new file mode 100644 index 0000000..5457898 --- /dev/null +++ b/Java/Spring/index.html @@ -0,0 +1,3309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Spring - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Spring

+

All Spring beans are managed - they "live" inside a container, called "application context".

+

Second, each application has an entry point to that context. Web applications have a Servlet, JSFuses a el-resolver, etc. Also, there is a place where the application context is bootstrapped and all beans - autowired. In web applications this can be a startup listener.

+

Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context.

+

What is "living" in the application context? This means that the context instantiates the objects, not you. I.e. - you never make new UserServiceImpl() - the container finds each injection point and sets an instance there.

+

Spring and AWS

+

A New Way of Using Email for Support Apps: An AWS Tutorial

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Linux/Linux/index.html b/Linux/Linux/index.html new file mode 100644 index 0000000..b061a3e --- /dev/null +++ b/Linux/Linux/index.html @@ -0,0 +1,3487 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Linux Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Linux Cheatsheet

+ +

Vim

+

Vim Commands Cheat Sheet

+
:q
+:q!
+:wq
+:wq {file}
+
+:e[dit] {file}
+
+i  insert
+dd  delete [count] lines
+
+

Bash

+ +
#!/bin/bash
+
+varname=value
+echo $varname
+
+

Don't forget chmod +x filename

+

Amazon Linux

+

Amazon Linux Basics

+

Adding Packages

+
sudo yum update -y                  # all packages
+sudo yum install -y package_name
+sudo yum install -y httpd24 php56 mysql55-server php56-mysqlnd
+
+

Start a Service

+
sudo service docker start
+sudo service jenkins start
+sudo service nginx start
+
+

Autostarting a service on Amazon Linux

+ +
# check a service is configured for startup
+sudo chkconfig sshd
+echo $?  # 0 = configured for startup
+# or
+sudo chkconfig --list mysqld
+sudo chkconfig --list         # all services
+
+# add a service
+sudo chkconfig --add vsftpd
+sudo chkconfig mysqld on
+sudo chkconfig --level 3 httpd on  # specific runlevel
+
+

Linux Boot Process

+ +

You can also use a /etc/rc.d/rc.local script.

+

Running Commands on your Linux Instance at Launch

+
    +
  • Paste a user data script into the User data field
  • +
+
#!/bin/bash
+yum update -y
+yum install -y httpd24 php56 mysql55-server php56-mysqlnd
+service httpd start
+chkconfig httpd on
+groupadd www
+usermod -a -G www ec2-user
+chown -R root:www /var/www
+chmod 2775 /var/www
+find /var/www -type d -exec chmod 2775 {} +
+find /var/www -type f -exec chmod 0664 {} +
+echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php
+
+ +

File location: /etc/sysconfig/cloudinit

+

Cloud-init output log file: /var/log/cloud-init-output.log

+

Install the SSM Agent on EC2 Instances at Start-Up

+
#!/bin/bash
+cd /tmp
+curl https://amazon-ssm-region.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm -o amazon-ssm-agent.rpm
+yum install -y amazon-ssm-agent.rpm
+
+

Linux desktop

+

How can I connect to an Amazon EC2 Linux instance with desktop functionality from Windows?

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Linux/Virtualization/index.html b/Linux/Virtualization/index.html new file mode 100644 index 0000000..05788b3 --- /dev/null +++ b/Linux/Virtualization/index.html @@ -0,0 +1,3269 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Virtualization - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Markup_and_Documentation/Jekyll/index.html b/Markup_and_Documentation/Jekyll/index.html new file mode 100644 index 0000000..b2b6257 --- /dev/null +++ b/Markup_and_Documentation/Jekyll/index.html @@ -0,0 +1,3431 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Jekyll How-To - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Jekyll Basics

+

Jekyll Home Page

+

Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll’s GitHub repo. If you have questions, you can ask them on Jekyll Talk.

+

Jekyll source code

+

Guide to basic Jekyll

+

Jekyll Install How-To

+

Install Instructions

+ +
gem update --system
+
+
    +
  • Install Jekyll
  • +
+
gem install jekyll
+
+
    +
  • Test Jekyll
  • +
+
jekyll --version
+gem list jekyll
+
+
    +
  • Install bundler
  • +
+
gem install bundler
+
+

Bundler is a gem that manages other Ruby gems. It makes sure your gems and gem versions are compatible, and that you have all necessary dependencies each gem requires.

+
    +
  • Create a new site
  • +
+
# Create a new Jekyll site at ./myblog
+~ $ jekyll new myblog
+
+# Change into your new directory
+~ $ cd myblog
+
+

Jekyll installs a site that uses a gem-based theme called Minima.

+

With gem-based themes, some of the site’s directories (such as the assets, _layouts,_includes, and _sass directories) are stored in the theme’s gem, hidden from your immediate view. Yet all of the necessary directories will be read and processed during Jekyll’s build process.

+
    +
  • Build site locally
  • +
+
# Build the site on the preview server
+~/myblog $ bundle exec jekyll serve
+
+

Now browse to localhost:4000

+

Jekyll Quickstart

+

When you run bundle exec jekyll serve, Bundler uses the gems and versions as specified in Gemfile.lock to ensure your Jekyll site builds with no compatibility or dependency conflicts.

+

The Gemfile and Gemfile.lock files inform Bundler about the gem requirements in your site. If your site doesn’t have these Gemfiles, you can omit bundle exec and just run jekyll serve.

+
$ jekyll build
+# => The current folder will be generated into ./_site
+
+$ jekyll serve
+# => A development server will run at https://localhost:4000/
+# Auto-regeneration: enabled. Use `--no-watch` to disable.
+
+

Plugins

+
$ gem install jekyll-sitemap
+$ gem install jekyll-feed
+etc...
+
+

Add to _config.yml

+
gems:
+  - jekyll-paginate
+  - jekyll-feed
+  - jekyll-sitemap
+``
+
+
+# Custom Search
+
+[Adding a custom Google search](https://digitaldrummerj.me/blogging-on-github-part-7-adding-a-custom-google-search/)
+
+
+# Themes
+
+[Theme documentation](https://jekyllrb.com/docs/themes/)
+
+To change theme, search for jekyll theme on [RubyGems](https://rubygems.org/search?utf8=%E2%9C%93&query=jekyll-theme) to find other gem-based themes.
+
+Add the theme to your site’s Gemfile:
+
+```bash
+gem "jekyll-theme-tactile"
+
+
$ bundle install
+
+# check proper install
+$ bundle show jekyll-theme-tactile
+
+

Add the following to your site’s _config.yml to activate the theme:

+
theme: jekyll-theme-tactile
+
+

Build your site:

+
bundle exec jekyll serve
+
+

You can find out info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at jekyllrb.com

+

You can find the source code for the Jekyll minima theme at: +minima

+
+

You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated.

+

To add new posts, simply add a file in the _posts directory that follows the convention YYYY-MM-DD-name-of-post.ext and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works.

+

Jekyll also offers powerful support for code snippets:

+
{% highlight ruby %}
+def print_hi(name)
+  puts "Hi, #{name}"
+end
+print_hi('Tom')
+# => prints 'Hi, Tom' to STDOUT.
+{% endhighlight %}
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Markup_and_Documentation/Markdown/index.html b/Markup_and_Documentation/Markdown/index.html new file mode 100644 index 0000000..83baff4 --- /dev/null +++ b/Markup_and_Documentation/Markdown/index.html @@ -0,0 +1,3468 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Markdown Essentials - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Markdown Essentials

+

Markdown main site

+

GitHub Flavored Markdown Guide

+

Basics

+

A paragraph is one or more consecutive lines of text separated by one or more blank lines. A blank line contains nothing but spaces or tabs.

+

Do not indent normal paragraphs with spaces or tabs. Indent at least 4 spaces or a tab for code blocks.

+
Syntax highlighted code block
+
+# Header 1
+## Header 2
+### Header 3
+
+- Bulleted
+- List
+
+1. Numbered
+2. List
+
+**Bold** and _Italic_ and `Code` text
+
+[Link](url) and ![Image](src)
+
+

Emphasis

+
 *single asterisks*
+ _single underscores_
+ **double asterisks**
+ __double underscores__
+
+

Emphasis can be used in the mi\*dd\*le of a word.

+

Headers

+
 # H1
+ ## H2
+ ### H3
+ #### H4
+ ##### H5
+ ###### H6
+
+ Alt-H1
+ ======
+
+ Alt-H2
+ ------
+
+ +
 [Text for the link](URL)
+
+ This is [an example][id] reference-style link.
+ [id]: https://example.com/  "Optional Title Here"
+
+ ![Alt text](/path/to/img.jpg "Optional title")
+
+

Code

+

span of code

+
```python
+
+ def wiki_rocks(text):
+  formatter = lambda t: "funky"+t
+  return formatter(text)
+```
+
+

will be displayed as

+
def wiki_rocks(text):
+ formatter = lambda t: "funky"+t
+ return formatter(text)
+
+

Blockquotes

+
 > This is a blockquote with two paragraphs.
+ >
+ > Second paragraph.
+
+

GitHub Pages

+

GitHub Pages documentation

+

GitHub Pages site will use the layout and styles from the Jekyll theme you have selected in your repository settings. The name of this theme is saved in the Jekyll _config.yml configuration file.

+

Bitbucket

+

Bitbucket doesn't support arbitrary HTML in Markdown, it instead uses safe mode. +Safe mode requires that you replace, remove, or escape HTML tags appropriately.

+

Code highlighting to bitbucket README.md written in Python Markdown

+

:::python + friends = ['john', 'pat', 'gary', 'michael'] + for i, name in enumerate(friends): + print "iteration {iteration} is {name}".format(iteration=i, name=name)

+

Python markdown main site

+

Cloning your Bitbucket Wiki

+
git clone https://bitbucket.org/MY_USER/MY_REPO/wiki
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Markup_and_Documentation/MkDocs/index.html b/Markup_and_Documentation/MkDocs/index.html new file mode 100644 index 0000000..c8257d6 --- /dev/null +++ b/Markup_and_Documentation/MkDocs/index.html @@ -0,0 +1,3357 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MkDocs Basics - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

MkDocs Basics

+ +

This website is generated by mkdocs.org and the Material Theme.

+

Basic MkDocs Commands

+
    +
  • mkdocs new [dir-name] - Create a new project.
  • +
  • mkdocs serve - Start the live-reloading docs server.
  • +
  • mkdocs build - Build the documentation site.
  • +
  • mkdocs help - Print this help message.
  • +
+

Install and documentation generation

+

mkdocs.org.

+

To install MkDocs / create a new documentation site:

+
pip install mkdocs
+mkdocs new documentation
+
+

To build the documentation site:

+
cd documentation
+mkdocs build
+
+

To start the live-reloading docs server - https://localhost:8000/

+
mkdocs serve
+
+

MkDocs can use the ghp-import tool to commit to the gh-pages branch and push the gh-pages branch to GitHub Pages:

+
mkdocs gh-deploy
+
+

MkDocs project layout

+
    mkdocs.yml    # The configuration file.
+    docs/
+        index.md  # The documentation homepage.
+        ...       # Other markdown pages, images and other files.
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Markup_and_Documentation/reStructuredText/index.html b/Markup_and_Documentation/reStructuredText/index.html new file mode 100644 index 0000000..9715a89 --- /dev/null +++ b/Markup_and_Documentation/reStructuredText/index.html @@ -0,0 +1,3666 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + reStructuredText Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

reStructuredText

+

reStructuredText Quick Ref

+

reStructuredText Cheat Sheet (see below)

+

reST Short Overview

+

All reST files use an indentation of 3 spaces; no tabs are allowed. +The maximum line length is 80 characters for normal text, but tables, +deeply indented code samples and long links may extend beyond that. +Code example bodies should use normal Python 4-space indentation. +Paragraphs are simply chunks of text separated by one or more blank lines. +As in Python, indentation is significant in reST, so all lines of the same +paragraph must be left-aligned to the same level of indentation.

+

Section headers are created by underlining (and optionally overlining) +the section title with a punctuation character, at least as long as the text:

+
 =================
+ This is a heading
+ =================
+ # with overline, for parts
+ * with overline, for chapters
+ = for sections
+ - for subsections
+ ^ for subsubsections
+ " for paragraphs
+
+ one asterisk: *text* for emphasis (italics),
+ two asterisks: **text** for strong emphasis (boldface), and
+ backquotes: ``text`` for code samples.
+ escape with a backslash \
+
+ * This is a bulleted list.
+ * It has two items, the second
+   item uses two lines.
+
+ 1. This is a numbered list.
+ 2. It has two items too.
+
+ . This is a numbered list.
+ . It has two items too.
+
+

Nested lists are possible, but be aware that they must be separated from the +parent list items by blank lines

+

Source Code Double Colon

+
This is a normal text paragraph. The next paragraph is a code sample::
+
+    It is not processed in any way, except
+    that the indentation is removed.
+
+    It can span multiple lines.
+
+This is a normal text paragraph again.
+
+ +

Link text <https://target>_ for inline web links.

+

Definitions

+
 term (up to a line of text)
+    Definition of the term, which must be indented and
+    can even consist of multiple paragraphs
+
+ next term
+    Description.
+
+

Footnotes

+
 Lorem ipsum [#]_ dolor sit amet ... [#]_
+
+

Use of reStructuredText in Python docstrings

+

See https://infinitemonkeycorps.net/docs/pph/

+
 # Typical function documentation:
+
+ :param volume_id: The ID of the EBS volume to be attached.
+ :type volume_id: str
+
+ :param instance_id: The ID of the EC2 instance
+ :type instance_id: str
+
+ :return: `Reverse geocoder return value`_ dictionary giving closest
+  address(es) to `(lat, lng)`
+ :rtype: dict
+ :raises GoogleMapsError: If the coordinates could not be reverse geocoded.
+
+ Keyword arguments and return value are identical to those of :meth:`geocode()`.
+
+ .. _`Reverse geocoder return value`:
+  https://code.google.com/apis/maps/documentation/geocoding/index.html#ReverseGeocoding
+
+
    +
  • Normal docstring formatting conventions apply: see PEP 257.
  • +
  • Identifier references go in `backticks`.
  • +
  • :param lat: some text documents parameters
  • +
  • :type lat: float documents parameter types
  • +
  • :return: dictionary giving some info... documents return values
  • +
  • :rtype: dict documents return type
  • +
  • :raises SomeError: sometext... documents exceptions raised
  • +
  • >>> starts a doctest and is automatically formatted as code
  • +
  • Code can also be indicated by indenting four spaces or preceding with :: and a blank line
  • +
  • Link to other methods, functions, classes, modules with :meth:mymethod,
  • +
  • :func:myfunc, :class:myclass, and :mod:mymodule.
  • +
  • Hyperlink names go in backticks with a trailing underscore: Google_
  • +
  • Targets can be defined anywhere with: .. _Google: https://www.google.com/
  • +
+

Explicit Markup

+

An explicit markup block begins with a line starting with .. followed by +whitespace and is terminated by the next paragraph at the same level of +indentation. (There needs to be a blank line between explicit markup +and normal paragraphs.

+
 .. sectionauthor:: Guido van Rossum <guido@python.org>
+
+ .. rubric:: Footnotes
+
+ .. [#] Text of the first footnote.
+ .. [#] Text of the second footnote.
+
+
+ :mod:`parrot` -- Dead parrot access
+ ===================================
+
+ .. module:: parrot
+    :platform: Unix, Windows
+    :synopsis: Analyze and reanimate dead parrots.
+ .. moduleauthor:: Eric Cleese <eric@python.invalid>
+ .. moduleauthor:: John Idle <john@python.invalid>
+
+ .. function:: repeat([repeat=3[, number=1000000]])
+      repeat(y, z)
+    :bar: no
+
+    Return a line of text input from the user.
+
+
+ .. class:: Spam
+
+    Description of the class.
+
+    .. data:: ham
+
+    Description of the attribute.
+
+

Inline markup

+
 :rolename:`content`  or  :role:`title <target>`
+
+ :meth:`~Queue.Queue.get` will refer to Queue.Queue.get but only display get as the link text.
+
+

The following roles refer to objects in modules and are possibly hyperlinked +if a matching identifier is found:

+

mod

+

The name of a module; a dotted name may be used. This should also be used for package names.

+

func

+

The name of a Python function; dotted names may be used. The role text should not include trailing parentheses to enhance readability. The parentheses are stripped when searching for identifiers.

+

data

+

The name of a module-level variable or constant.

+

const

+

The name of a “defined” constant. This may be a C-language #define or a Python variable that is not intended to be changed.

+

class

+

A class name; a dotted name may be used.

+

meth

+

The name of a method of an object. The role text should include the type name and the method name. A dotted name may be used.

+

attr

+

The name of a data attribute of an object.

+

exc

+

The name of an exception. A dotted name may be used.

+

Official reStructuredText Cheatsheet

+
 =====================================================
+  The reStructuredText_ Cheat Sheet: Syntax Reminders
+ =====================================================
+ :Info: See <https://docutils.sf.net/rst.html> for introductory docs.
+ :Author: David Goodger <goodger@python.org>
+ :Date: $Date: 2013-02-20 01:10:53 +0000 (Wed, 20 Feb 2013) $
+ :Revision: $Revision: 7612 $
+ :Description: This is a "docinfo block", or bibliographic field list
+
+ .. NOTE:: If you are reading this as HTML, please read
+    `<cheatsheet.txt>`_ instead to see the input syntax examples!
+
+ Section Structure
+ =================
+ Section titles are underlined or overlined & underlined.
+
+ Body Elements
+ =============
+ Grid table:
+
+ +--------------------------------+-----------------------------------+
+ | Paragraphs are flush-left,     | Literal block, preceded by "::":: |
+ | separated by blank lines.      |                                   |
+ |                                |     Indented                      |
+ |     Block quotes are indented. |                                   |
+ +--------------------------------+ or::                              |
+ | >>> print 'Doctest block'      |                                   |
+ | Doctest block                  | > Quoted                          |
+ +--------------------------------+-----------------------------------+
+ | | Line blocks preserve line breaks & indents. [new in 0.3.6]       |
+ | |     Useful for addresses, verse, and adornment-free lists; long  |
+ |       lines can be wrapped with continuation lines.                |
+ +--------------------------------------------------------------------+
+
+ Simple tables:
+
+ ================  ============================================================
+ List Type         Examples (syntax in the `text source <cheatsheet.txt>`_)
+ ================  ============================================================
+ Bullet list       * items begin with "-", "+", or "*"
+ Enumerated list   1. items use any variation of "1.", "A)", and "(i)"
+       #. also auto-enumerated
+ Definition list   Term is flush-left : optional classifier
+        Definition is indented, no blank line between
+ Field list        :field name: field body
+ Option list       -o  at least 2 spaces between option & description
+ ================  ============================================================
+
+ ================  ============================================================
+ Explicit Markup   Examples (visible in the `text source`_)
+ ================  ============================================================
+ Footnote          .. [1] Manually numbered or [#] auto-numbered
+       (even [#labelled]) or [*] auto-symbol
+ Citation          .. [CIT2002] A citation.
+ Hyperlink Target  .. _reStructuredText: https://docutils.sf.net/rst.html
+       .. _indirect target: reStructuredText_
+       .. _internal target:
+ Anonymous Target  __ https://docutils.sf.net/docs/ref/rst/restructuredtext.html
+ Directive ("::")  .. image:: images/biohazard.png
+ Substitution Def  .. |substitution| replace:: like an inline directive
+ Comment           .. is anything else
+ Empty Comment     (".." on a line by itself, with blank lines before & after,
+       used to separate indentation contexts)
+ ================  ============================================================
+
+ Inline Markup
+ =============
+ *emphasis*; **strong emphasis**; `interpreted text`; `interpreted text
+ with role`:emphasis:; ``inline literal text``; standalone hyperlink,
+ https://docutils.sourceforge.net; named reference, reStructuredText_;
+ `anonymous reference`__; footnote reference, [1]_; citation reference,
+ [CIT2002]_; |substitution|; _`inline internal target`.
+
+ Directive Quick Reference
+ =========================
+ See <https://docutils.sf.net/docs/ref/rst/directives.html> for full info.
+
+ ================  ============================================================
+ Directive Name    Description (Docutils version added to, in [brackets])
+ ================  ============================================================
+ attention         Specific admonition; also "caution", "danger",
+       "error", "hint", "important", "note", "tip", "warning"
+ admonition        Generic titled admonition: ``.. admonition:: By The Way``
+ image             ``.. image:: picture.png``; many options possible
+ figure            Like "image", but with optional caption and legend
+ topic             ``.. topic:: Title``; like a mini section
+ sidebar           ``.. sidebar:: Title``; like a mini parallel document
+ parsed-literal    A literal block with parsed inline markup
+ rubric            ``.. rubric:: Informal Heading``
+ epigraph          Block quote with class="epigraph"
+ highlights        Block quote with class="highlights"
+ pull-quote        Block quote with class="pull-quote"
+ compound          Compound paragraphs [0.3.6]
+ container         Generic block-level container element [0.3.10]
+ table             Create a titled table [0.3.1]
+ list-table        Create a table from a uniform two-level bullet list [0.3.8]
+ csv-table         Create a table from CSV data [0.3.4]
+ contents          Generate a table of contents
+ sectnum           Automatically number sections, subsections, etc.
+ header, footer    Create document decorations [0.3.8]
+ target-notes      Create an explicit footnote for each external target
+ math              Mathematical notation (input in LaTeX format)
+ meta              HTML-specific metadata
+ include           Read an external reST file as if it were inline
+ raw               Non-reST data passed untouched to the Writer
+ replace           Replacement text for substitution definitions
+ unicode           Unicode character code conversion for substitution defs
+ date              Generates today's date; for substitution defs
+ class             Set a "class" attribute on the next element
+ role              Create a custom interpreted text role [0.3.2]
+ default-role      Set the default interpreted text role [0.3.10]
+ title             Set the metadata document title [0.3.10]
+ ================  ============================================================
+
+ Interpreted Text Role Quick Reference
+ =====================================
+ See <https://docutils.sf.net/docs/ref/rst/roles.html> for full info.
+
+ ================  ============================================================
+ Role Name         Description
+ ================  ============================================================
+ emphasis          Equivalent to *emphasis*
+ literal           Equivalent to ``literal`` but processes backslash escapes
+ math              Mathematical notation (input in LaTeX format)
+ PEP               Reference to a numbered Python Enhancement Proposal
+ RFC               Reference to a numbered Internet Request For Comments
+ raw               For non-reST data; cannot be used directly (see docs) [0.3.6]
+ strong            Equivalent to **strong**
+ sub               Subscript
+ sup               Superscript
+ title             Title reference (book, etc.); standard default role
+ ================  ============================================================
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Microservices/Microservices/index.html b/Microservices/Microservices/index.html new file mode 100644 index 0000000..3fc2e62 --- /dev/null +++ b/Microservices/Microservices/index.html @@ -0,0 +1,3334 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Microservices - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Privacy/Privacy_engineering/index.html b/Privacy/Privacy_engineering/index.html new file mode 100644 index 0000000..44c8a34 --- /dev/null +++ b/Privacy/Privacy_engineering/index.html @@ -0,0 +1,3308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Privacy Engineering - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Python/Flask/index.html b/Python/Flask/index.html new file mode 100644 index 0000000..88a491c --- /dev/null +++ b/Python/Flask/index.html @@ -0,0 +1,3311 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Flask - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Python/Jupyter/index.html b/Python/Jupyter/index.html new file mode 100644 index 0000000..c91e46c --- /dev/null +++ b/Python/Jupyter/index.html @@ -0,0 +1,3542 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IPython / Jupyter Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

IPython / Jupyter Cheatsheet

+ +

IPython / Jupyter

+
    +
  • Using IPython makes interactive work easy.
  • +
  • Better shell
  • +
  • Notebook interface
  • +
  • Embeddable kernel
  • +
  • Parallel python
  • +
+

IPython shell shortcuts

+
    +
  • TAB expansion to complete python names and file paths
  • +
  • ~ and * directory / file expansion
  • +
  • many "magic" methods:
  • +
+
%lsmagic                # list of all magic methods
+%quickref               # cheatsheet
+%magic
+
+

Help

+
?                       # overall help
+help                    # python help system
+?someobj or someobj?    # help
+??someobj or someobj??  # detailed help
+
+

%pdoc %pdef %psource for docstring, function definition, source code only.

+

Run

+

To run a program directly from the IPython console:

+
%run somescript.py      # instead of execfile("somescript.py") at the python prompt
+
+

%run has special flags for timing the execution of your scripts (-t) or for running them under the control of either Python's pdb debugger (-d) or profiler (-p):

+
%run -d myscript.py
+
+

Other Commands

+
%edit %ed               # edit then execute
+%save
+%load example.py        # load local (example) file (or url) allowing modification
+%load https://matplotlib.org/plot_directive/mpl_examples/mplot3d/contour3d_demo.py
+%macro                  # define macro with range of history lines, filenames or string objects
+%recall
+
+%whos                   # list identifiers you have defined interactively
+%reset  -f -s           # remove objects -f for force -s for soft (leaves history).
+
+
    +
  • %reset is not a kernel restart
  • +
  • Restart with Ctrl+. in "qtconsole"
  • +
  • import module ; reload(module) to reload a module from disk
  • +
+

Debugging

+
%debug                  # jump into the Python debugger (pdb)
+%pdb                    # start the debugger on any uncaught exception.
+
+%cd                     # change directory
+%pwd                    # print working directory
+%env                    # OS environment variables
+
+

OS Commands

+
!OScommand
+!ping www.bbc.co.uk
+%alias                  # system command alias
+
+

History

+
_ __ ___                # etc... for previous outputs.
+_i _ii _i4              # etc.. for previous input. _ih for list of previous inputs
+
+

GUI integration

+

Start with ipython --gui=qt or at the IPython prompt:

+
%gui wx
+
+

Arguments can be wx, qt, gtk and tk.

+

Matplotlib / pylab graphics in an iPython shell

+

Start with: ipython --matplotlib ( or --matplotlib=qt etc...)

+

At the IPython prompt:

+
%matplotlib             # set matplotlib to work interactively; does not import anythig
+%matplotlib  inline
+%matplotlib qt          # request a specific GUI backend
+%pylab inline
+
+

%pylab makes the following imports:

+
import numpy
+import matplotlib
+from matplotlib import pylab, mlab, pyplot
+np = numpy
+plt = pyplot
+from IPython.display import display
+from IPython.core.pylabtools import figsize, getfigs
+from pylab import *
+from numpy import *
+
+

Qtconsole - an improved console

+

At the command prompt:

+
ipython.exe qtconsole --pylab=inline --ConsoleWidget.font_size=10
+
+

alternative: --matplotlib inline +or within IPython:

+
%matplotlib  inline
+%pylab inline
+
+

To embed plots, SVG or HTML in qtconsole, call display:

+
from IPython.core.display import display, display_html
+from IPython.core.display import display_png, display_svg
+display(plt.gcf()) # embeds the current figure in the qtconsole
+display(*getfigs()) # embeds all active figures in the qtconsole
+#or:
+f = plt.figure()
+plt.plot(np.rand(100))
+display(f)
+
+

ipython and ipython notebook for matlab users

+

IPython Notebook web-based interface

+
    +
  • Start with: ipython notebook and switch to browser
  • +
  • Keyboard shortcuts:
  • +
  • Enter to edit a cell
  • +
  • Shift + Enter to evaluate
  • +
  • Ctrl + m or Esc for the "command mode"
  • +
+

In command mode:

+
     h list of keyboard shortcuts
+     1-6 to convert to heading cell
+     m to convert to markdown cell
+     y to convert to code
+     c copy / v paste
+     d d delete cell
+     s save notebook
+     . to restart kernel
+
+

Papermill

+

Papermill

+

Papermill is a tool for parameterizing and executing Jupyter Notebooks.

+

Papermill GitHub

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Python/Matplotlib/index.html b/Python/Matplotlib/index.html new file mode 100644 index 0000000..42c4352 --- /dev/null +++ b/Python/Matplotlib/index.html @@ -0,0 +1,3360 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Matplotlib Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Matplotlib Cheatsheet

+

Matplotlib prepares 2D (and some 3D) graphics.

+ + +
    +
  • Matplotlib is the whole package. Pylab and matplotlib.pyplot (pyplot in the following) are modules in matplotlib.
  • +
  • Pyplot makes matplotlib work like MATLAB.
  • +
  • Pyplot provides the state-machine interface to the underlying plotting library (the matplotlib API in the matplotlib module).
  • +
  • Each pyplot function makes some change to a figure: eg, create a figure, create a plotting area in a figure, plot some lines in a plotting area, decorate the plot with labels, etc....
  • +
  • Pyplot is stateful, in that it keeps track of the current figure and plotting area, and the plotting functions are directed to the current axes.
  • +
  • Pylab combines the pyplot functionality (for plotting) with the numpy functionality (mathematics / arrays) in a single namespace, making that namespace (or environment) even more MATLAB-like.
  • +
  • The pyplot interface is generally preferred for non-interactive plotting (i.e., scripting).
  • +
  • The pylab interface is convenient for interactive calculations and plotting, as it minimizes typing.
  • +
+

Examples

+
import numpy as np
+import matplotlib.pyplot as plt
+
+# Compute the x and y coordinates for points on sine and cosine curves
+x = np.arange(0, 3 * np.pi, 0.1)
+y_sin = np.sin(x)
+y_cos = np.cos(x)
+
+# Set up a subplot grid that has height 2 and width 1,
+# and set the first such subplot as active.
+plt.subplot(2, 1, 1)
+
+# Make the first plot
+plt.plot(x, y_sin)
+plt.title('Sine')
+
+# Set the second subplot as active, and make the second plot.
+plt.subplot(2, 1, 2)
+plt.plot(x, y_cos)
+plt.title('Cosine')
+
+# Show the figure.
+plt.show()
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Python/Python/index.html b/Python/Python/index.html new file mode 100644 index 0000000..477270c --- /dev/null +++ b/Python/Python/index.html @@ -0,0 +1,3377 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Python Links - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Python useful links

+

Python environments

+

venv — Creation of virtual environments

+
python3 -m venv /path/to/new/virtual/environment
+
+

Virtualenv

+

virtualenv is a tool to create isolated Python environments. Since Python 3.3, a subset of it has been integrated into the standard library under the venv module. Note though, that the venv module does not offer all features of this library (e.g. cannot create bootstrap scripts, cannot create virtual environments for other python versions than the host python, not relocatable, etc.).

+

pip-tools

+

A set of command line tools to help you keep your pip-based packages fresh, even when you've pinned them.

+

Pipenv

+

The problems that Pipenv seeks to solve are multi-faceted:

+
    +
  • You no longer need to use pip and virtualenv separately. They work together.
  • +
  • Managing a requirements.txt file can be problematic, so Pipenv uses Pipfile and Pipfile.lock to separate abstract dependency declarations from the last tested combination.
  • +
  • Hashes are used everywhere, always. Security. Automatically expose security vulnerabilities.
  • +
  • Strongly encourage the use of the latest versions of dependencies to minimize security risks arising from outdated components.
  • +
  • Give you insight into your dependency graph (e.g. $ pipenv graph).
  • +
  • Streamline development workflow by loading .env files.
  • +
+

Pyenv for managing multiple Python versions

+

Testing

+

Mockito

+

Code coverage measurement for Python

+

mechanize - Automate interaction with HTTP web servers

+

Packaging

+

Cookiecutter template for a Python package

+

Python Packaging User Guide

+

Twine

+

Twine is a utility for publishing Python packages on PyPI.

+

Build tools

+

Buildout, an automation tool written in and extended with Python

+

PyBuilder

+

Uranium: a Python Build System

+

Other

+

Python Anywhere

+

Host, run, and code Python in the cloud

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Python/Python3/index.html b/Python/Python3/index.html new file mode 100644 index 0000000..cf72bfa --- /dev/null +++ b/Python/Python3/index.html @@ -0,0 +1,3528 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Python 3 - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Python 3

+ +

What's new in Python 3.x

+

What's really new in Python 3

+

nonlocal / global

+
x = 0
+def outer():
+  x = 1
+  def inner():
+  nonlocal x
+  x = 2
+  print("inner:", x)
+
+  inner()
+  print("outer:", x)
+
+outer()
+print("global:", x)
+
+# inner: 2
+# outer: 2
+# global: 0
+
+## with global
+x = 0
+def outer():
+     x = 1
+     def inner():
+           global x
+           x = 2
+           print("inner:", x)
+  inner()
+  print("outer:", x)
+outer()
+print("global:", x)
+
+# inner: 2
+# outer: 1
+# global: 2
+
+

String interpolation - new in 3.6

+
name="David"
+f"My name is {name}"
+value = decimal.Decimal("10.4507")
+print(f"result: {value:10.5}" )  # width precision
+
+

PEP 492 - Coroutines with async and await syntax

+

async and await

+

yield from iterator

+

is equivalent

+
for x in iterator:
+     yield x
+
+

Example:

+
def lazy_range(up_to):
+     """Generator to return the sequence of integers from 0 to up_to, exclusive."""
+     index = 0
+     def gratuitous_refactor():
+           nonlocal index
+           while index < up_to:
+               yield index
+               index += 1
+     yield from gratuitous_refactor()
+
+

New 3.6 syntax:

+
async def func(param1, param2):
+    do_stuff()
+    await some_coroutine()
+
+async def read_data(db):
+  data = await db.fetch('SELECT ...')
+
+async def display_date(loop):
+  end_time = loop.time() + 5.0
+  while True:
+  print(datetime.datetime.now())
+  if (loop.time() + 1.0) >= end_time:
+  break
+  await asyncio.sleep(1)
+
+
+loop = asyncio.get_event_loop()# Blocking call which returns when the display_date() coroutine is done
+loop.run_until_complete(display_date(loop))
+loop.close()
+
+

Async for

+
async for TARGET in ITER:
+  BLOCK
+else:
+  BLOCK2
+
+

Async improvements - 3.6

+
    +
  • set comprehension: {i async for i in agen()}
  • +
  • list comprehension: [i async for i in agen()]
  • +
  • dict comprehension: {i: i ** 2 async for i in agen()}
  • +
  • generator expression: (i ** 2 async for i in agen())
  • +
+

Type hinting

+

PEP 484

+

mypy-lang.org

+
def greet(name: str) -> str
+    return 'Hello there, {}'.format(name)
+
+

Type aliases

+
Url = str
+def retry(url: Url, retry_count: int) -> None: ...
+
+
from typing import TypeVar, Iterable, Tuple
+
+

Other common typings include: Any; Generic, Dict, List, Optional, Mapping, Set, Sequence - expressed as Sequence[int]

+
T = TypeVar('T', int, float, complex)  # T is either or an int, a float or a complex
+Vector = Iterable[Tuple[T, T]]          #
+
+def inproduct(v: Vector[T]) -> T:
+       return sum(x*y for x, y in v)
+
+def dilate(v: Vector[T], scale: T) -> Vector[T]:
+       return ((x * scale, y * scale) for x, y in v)
+vec = [] # type: Vector[float]
+
+

For functions

+
Callable[[Arg1Type, Arg2Type], ReturnType]
+
+

Type comments

+
x = []   # type: List[Employee]
+x, y, z = [], [], []  # type: List[int], List[int], List[str]
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Scala/Akka/index.html b/Scala/Akka/index.html new file mode 100644 index 0000000..cf1418b --- /dev/null +++ b/Scala/Akka/index.html @@ -0,0 +1,3423 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Akka Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Akka

+

Actors have:

+
    +
  • A mailbox (the queue where messages end up).
  • +
  • A behavior (the state of the actor, internal variables etc.).
  • +
  • Messages (pieces of data representing a signal, similar to method calls and their parameters).
  • +
  • An execution environment (the machinery that takes actors that have messages to react to and invokes their message handling code).
  • +
  • An address.
  • +
+

sbt:

+
libraryDependencies ++= Seq(
+  "com.typesafe.akka" %% "akka-actor" % "2.5.6",
+  "com.typesafe.akka" %% "akka-testkit" % "2.5.6" % Test
+)
+
+

Basic Example

+
//#full-example
+package com.lightbend.akka.sample
+
+import akka.actor.{ Actor, ActorLogging, ActorRef, ActorSystem, Props }
+import scala.io.StdIn
+
+//#greeter-companion
+//#greeter-messages
+object Greeter {
+  //#greeter-messages
+  def props(message: String, printerActor: ActorRef): Props = Props(new Greeter(message, printerActor))
+  //#greeter-messages
+  final case class WhoToGreet(who: String)
+  case object Greet
+}
+//#greeter-messages
+//#greeter-companion
+
+//#greeter-actor
+class Greeter(message: String, printerActor: ActorRef) extends Actor {
+  import Greeter._
+  import Printer._
+
+  var greeting = ""
+
+  def receive = {
+    case WhoToGreet(who) =>
+      greeting = s"$message, $who"
+    case Greet           =>
+      //#greeter-send-message
+      printerActor ! Greeting(greeting)
+      //#greeter-send-message
+  }
+}
+//#greeter-actor
+
+//#printer-companion
+//#printer-messages
+object Printer {
+  //#printer-messages
+  def props: Props = Props[Printer]
+  //#printer-messages
+  final case class Greeting(greeting: String)
+}
+//#printer-messages
+//#printer-companion
+
+//#printer-actor
+class Printer extends Actor with ActorLogging {
+  import Printer._
+
+  def receive = {
+    case Greeting(greeting) =>
+      log.info(s"Greeting received (from ${sender()}): $greeting")
+  }
+}
+//#printer-actor
+
+//#main-class
+object AkkaQuickstart extends App {
+  import Greeter._
+
+  // Create the 'helloAkka' actor system
+  val system: ActorSystem = ActorSystem("helloAkka")
+
+  try {
+    //#create-actors
+    // Create the printer actor
+    val printer: ActorRef = system.actorOf(Printer.props, "printerActor")
+
+    // Create the 'greeter' actors
+    val howdyGreeter: ActorRef =
+      system.actorOf(Greeter.props("Howdy", printer), "howdyGreeter")
+    val helloGreeter: ActorRef =
+      system.actorOf(Greeter.props("Hello", printer), "helloGreeter")
+    val goodDayGreeter: ActorRef =
+      system.actorOf(Greeter.props("Good day", printer), "goodDayGreeter")
+    //#create-actors
+
+    //#main-send-messages
+    howdyGreeter ! WhoToGreet("Akka")
+    howdyGreeter ! Greet
+
+    howdyGreeter ! WhoToGreet("Lightbend")
+    howdyGreeter ! Greet
+
+    helloGreeter ! WhoToGreet("Scala")
+    helloGreeter ! Greet
+
+    goodDayGreeter ! WhoToGreet("Play")
+    goodDayGreeter ! Greet
+    //#main-send-messages
+
+    println(">>> Press ENTER to exit <<<")
+    StdIn.readLine()
+  } finally {
+    system.terminate()
+  }
+}
+//#main-class
+//#full-example
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Scala/Play_Framework/index.html b/Scala/Play_Framework/index.html new file mode 100644 index 0000000..221408d --- /dev/null +++ b/Scala/Play_Framework/index.html @@ -0,0 +1,3349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Play Framework - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Play Framework

+ + +

Play Framework

+

The Play application layout

+

The layout of a Play application is standardized to keep things as simple as possible. After a first successful compile, a Play application looks like this:

+
app                      → Application sources
+ └ assets                → Compiled asset sources
+    └ stylesheets        → Typically LESS CSS sources
+    └ javascripts        → Typically CoffeeScript sources
+ └ controllers           → Application controllers
+ └ models                → Application business layer
+ └ views                 → Templates
+build.sbt                → Application build script
+conf                     → Configurations files and other non-compiled resources (on classpath)
+ └ application.conf      → Main configuration file
+ └ routes                → Routes definition
+dist                     → Arbitrary files to be included in your projects distribution
+public                   → Public assets
+ └ stylesheets           → CSS files
+ └ javascripts           → Javascript files
+ └ images                → Image files
+project                  → sbt configuration files
+ └ build.properties      → Marker for sbt project
+ └ plugins.sbt           → sbt plugins including the declaration for Play itself
+lib                      → Unmanaged libraries dependencies
+logs                     → Logs folder
+ └ application.log       → Default log file
+target                   → Generated stuff
+ └ resolution-cache      → Info about dependencies
+ └ scala-2.11
+    └ api                → Generated API docs
+    └ classes            → Compiled class files
+    └ routes             → Sources generated from routes
+    └ twirl              → Sources generated from templates
+ └ universal             → Application packaging
+ └ web                   → Compiled web assets
+test                     → source folder for unit or functional tests
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Scala/Scala_Collections/index.html b/Scala/Scala_Collections/index.html new file mode 100644 index 0000000..d814679 --- /dev/null +++ b/Scala/Scala_Collections/index.html @@ -0,0 +1,3697 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scala Collections - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Scala Collections

+ +

Examples from Scala Koans.

+

Core Packages

+

The scala package contains core types like Int, Float, Array or Option which are accessible in all Scala compilation units without explicit qualification or imports.

+

Notable packages include:

+
  scala.collection and its sub-packages contain Scala's collections framework
+  scala.collection.immutable - Immutable, sequential data-structures such as Vector, List, Range, HashMap or HashSet
+  scala.collection.mutable - Mutable, sequential data-structures such as ArrayBuffer, StringBuilder, HashMap or HashSet
+  scala.collection.concurrent - Mutable, concurrent data-structures such as TrieMap
+  scala.collection.parallel.immutable - Immutable, parallel data-structures such as ParVector, ParRange, ParHashMap or ParHashSet
+  scala.collection.parallel.mutable - Mutable, parallel data-structures such as ParArray, ParHashMap, ParTrieMap or ParHashSet
+
+  scala.concurrent - Primitives for concurrent programming such as Futures and Promises
+  scala.io - Input and output operations
+  scala.math - Basic math functions and additional numeric types like BigInt and BigDecimal
+  scala.sys - Interaction with other processes and the operating system
+  scala.util.matching - Regular expressions
+
+

Additional parts of the standard library are shipped as separate libraries. These include:

+
  scala.reflect - Scala's reflection API (scala-reflect.jar)
+  scala.xml - XML parsing, manipulation, and serialization (scala-xml.jar)
+  scala.swing - A convenient wrapper around Java's GUI framework called Swing (scala-swing.jar)
+  scala.util.parsing - Parser combinators (scala-parser-combinators.jar)
+  Automatic imports
+
+

Identifiers in the scala package and the scala.Predef object are always in scope by default.

+

Some of these identifiers are type aliases provided as shortcuts to commonly used classes. For example, List is an alias for scala.collection.immutable.List.

+

Other aliases refer to classes provided by the underlying platform. For example, on the JVM, String is an alias for java.lang.String.

+

Traversables

+

Traversables are the superclass of Lists, Arrays, Maps, Sets, Streams, and more. +The methods involved can be applied to each other in a different type.

+
val set = Set(1, 9, 10, 22)
+val list = List(3, 4, 5, 10)
+val result = set ++ list      // ++ appends two Traversables together.
+result.size
+result.isEmpty
+result.hasDefiniteSize      // false if a Stream
+
+
    +
  • Take some
  • +
+
list.head
+list.headOption
+list.tail
+list.lastOption
+result.last
+list.init            // collection without the last element
+list.slice(1, 3)
+list.take(3)
+list drop 6 take 3
+list.takeWhile(_ < 100)
+list.dropWhile(_ < 100)
+
+
    +
  • Filter, Map, Flatten
  • +
+
list.filter(_ < 100)
+list.filterNot(_ < 100)
+list.find(_ % 2 != 0)             // get first element that matches
+
+list.foreach(num => println(num * 4))    // side effect
+
+list.map(_ * 4)                // map
+
+val list = List(List(1), List(2, 3, 4), List(5, 6, 7), List(8, 9, 10))
+list.flatten
+list.flatMap(_.map(_ * 4))          // map then flatten
+
+val result = list.collect {          // apply a partial function to all elements of a Traversable and will return a different collection.
+      case x: Int if (x % 2 == 0) => x * 3
+    }
+// can use  orElse  or andThen
+
+
    +
  • Split
  • +
+
val array = Array(87, 44, 5, 4, 200, 10, 39, 100)  // splitAt - will split a Traversable at a position, returning a tuple.
+val result = array splitAt 3
+result._1
+result._2
+
+val result = array partition (_ < 100)         // partition will split a Traversable according to predicate, return a 2 product Tuple. The left side are the elements satisfied by the predicate, the right side is not.
+
+// groupBy returns a map e.g. Map( "Odd" -> ... , "Even" -> ...)
+val result = array groupBy { case x: Int if x % 2 == 0 => "Even"; case x: Int if x % 2 != 0 => "Odd" }
+
+
    +
  • Analyze
  • +
+
list forall (_ < 100)             // true if predicate true for all elements
+list exists (_ < 100)             // true if predicate true for any element
+list count (_ < 100)
+
+
    +
  • Reduce and Fold
  • +
+
list.foldLeft(0)(_ - _)
+(0 /: list)(_ - _)               // Short hand
+
+list.foldRight(0)(_ - _)
+(list :\ 0)(_ - _)               // Short hand
+
+list.reduceLeft { _ + _ }
+list.reduceRight { _ + _ }
+
+list.sum
+list.product
+list.max
+list.min
+
+val list = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
+list.transpose
+
+
    +
  • Conversions; toList, as well as other conversion methods like toSet, toArray will not convert if the collection type is the same.
  • +
+
list.toArray
+list.toSet
+set.toList
+set.toIterable
+set.toSeq
+set.toIndexedSeq
+list.toStream
+
+val list = List("Phoenix" -> "Arizona", "Austin" -> "Texas")  // elements should be tuples
+val result = list.toMap
+
+
    +
  • Print
  • +
+
result.mkString(",")
+list.mkString(">", ",", "<")
+val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
+stringBuilder.append("I want all numbers 6-12: ")
+list.filter(it => it > 5 && it < 13).addString(stringBuilder, ",")
+stringBuilder.mkString
+
+

Lists

+
val a = List(1, 2, 3)      // immutable
+val b = 1 :: 2 :: 3 :: Nil  // cons notation
+(a == b)   // true
+a eq b     // false
+a.length
+a.head
+a.tail
+a.reverse          // reverse the list
+a.map {v => v * 2}       // or a.map {_ * 2} or a.map(_ * 2)
+a.filter {v => v % 3 == 0}
+a.filterNot(v => v == 5)   // remove where value is 5
+a.reduceLeft(_ + _)      // note the two _s below indicate the first and second args respectively
+a.foldLeft(10)(_ + _)    // foldlLeft is like reduce, but with an explicit starting value
+(1 to 5).toList        // from range
+val a = a.toArray
+
+

Nil lists are identical, even of different types

+

Iterators

+
val list = List(3, 5, 9, 11, 15, 19, 21)
+val it = list.iterator
+if (it.hasNext) {
+  it.next should be(__)
+}
+
+val it = list grouped 3     // `grouped` will return an fixed sized Iterable chucks of an Iterable
+val it = list sliding 3      // `sliding` will return an Iterable that shows a sliding window of an Iterable.
+val it = list sliding(3, 3)   // `sliding` can take the size of the window as well the size of the step during each iteration
+list takeRight 3
+list dropRight 3
+
+val xs = List(3, 5, 9)      // `zip` will stitch two iterables into an iterable of pairs (tuples) of corresponding elements from both iterables.
+val ys = List("Bob", "Ann", "Stella")
+xs zip ys
+
+// If two Iterables aren't the same size, then `zip` will only zip what can only be paired.
+xs zipAll(ys, -1, "?")  // if two Iterables aren't the same size, then `zipAll` can provide fillers
+
+xs.zipWithIndex
+
+

Arrays, Sequences

+
val a = Array(1, 2, 3)
+val s = a.toSeq
+val l = s.toList
+
+
val s = Seq("hello", "to", "you")
+val filtered = s.filter(_.length > 2)
+val r = s map {
+      _.reverse
+    }
+val s = for (v <- 1 to 10 if v % 3 == 0) yield v  // create a sequence from a for comprehension with an optional condition
+s.toList
+
+

Lazy Collections and Streams

+
val strictList = List(10, 20, 30)
+val lazyList = strictList.view    // Strict collection always processes its elements but lazy collection does it on demand
+
+val infinite = Stream.from(1)
+infinite.take(4).sum
+Stream.continually(1).take(4).sum
+
+// Always remember tail of a lazy collection is never computed unless required
+
+def makeLazy(value: Int): Stream[Int] = {
+  Stream.cons(value, makeLazy(value + 1))
+}
+val stream = makeLazy(1)
+stream.head
+
+

Maps

+
val myMap = Map("MI" -> "Michigan", "OH" -> "Ohio", "WI" -> "Wisconsin", "MI" -> "Michigan")
+
+// access by key - Accessing a map by key results in an exception if key is not found
+myMap("MI")
+myMap.contains("IL")
+
+val aNewMap = myMap + ("IL" -> "Illinois")  // add - creates a new collection if immutable
+val aNewMap = myMap - "MI"          // remove - Attempted removal of nonexistent elements from a map is handled gracefully
+val aNewMap = myMap -- List("MI", "OH")     // remove multiples
+val aNewMap = myMap - ("MI", "WI") // Notice: single '-' operator for tuples
+
+var anotherMap += ("IL" -> "Illinois")     // compiler trick - creates a new collection and reassigns; note the 'var'
+
+// Map values can be iterated
+val mapValues = myMap.values
+mapValues.size
+mapValues.head
+mapValues.last
+
+for (mval <- mapValues) println(mval)
+// NOTE that the following will not compile, as iterators do not implement "contains"
+//mapValues.contains("Illinois")
+
+// Map keys may be of mixed type
+val myMap = Map("Ann Arbor" -> "MI", 49931 -> "MI")
+
+// Mixed type values can be added to a map
+val myMap = scala.collection.mutable.Map.empty[String, Any]
+myMap("Ann Arbor") = (48103, 48104, 48108)
+myMap("Houghton") = 49931
+
+// Map equivalency is independent of order
+val myMap1 = Map("MI" -> "Michigan", "OH" -> "Ohio", "WI" -> "Wisconsin", "IA" -> "Iowa")
+val myMap2 = Map("WI" -> "Wisconsin", "MI" -> "Michigan", "IA" -> "Iowa", "OH" -> "Ohio")
+myMap1.equals(myMap2)
+
+

Maps insertion with duplicate key updates previous entry with subsequent value

+
    +
  • Mutable Maps
  • +
+
val myMap = mutable.Map("MI" -> "Michigan", "OH" -> "Ohio", "WI" -> "Wisconsin", "IA" -> "Iowa")
+// same methods than immutable maps work
+val myMap += ("IL" -> "Illinois")    // this is a method; note the difference from immutable +=
+myMap.clear()               // Convention is to use parens if possible when method called changes state
+
+

Sets

+
val mySet = Set(1, 3, 4, 9)  // immutable
+val mySet = mutable.Set("Michigan", "Ohio", "Wisconsin", "Iowa")
+mySet.size
+mySet contains "Ohio"
+mySet += "Oregon"
+mySet += ("Iowa", "Ohio")
+mySet ++= List("Iowa", "Ohio")
+mySet -= "Ohio"
+mySet --= List("Iowa", "Ohio")
+mySet.clear()  // mutable only
+
+var sum = 0
+for (i <- mySet)  // for comprehension
+  sum = sum + i    // of course this is the same thing as mySet.reduce(_ + _)
+
+val mySet2 = Set("Wisconsin", "Michigan", "Minnesota")
+mySet intersect mySet2  // or & operator
+mySet1 union mySet2    // or | operator
+mySet2 subsetOf mySet1
+mySet1 diff mySet2
+mySet1.equals(mySet2)  // independent of order
+
+

Option[T]

+
val someValue: Option[String] = Some("I am wrapped in something")
+val nullValue: Option[String] = None
+someValue.get              // java.util.NoSuchElementException if None
+nullValue getOrElse "No value"
+nullValue.isEmpty
+
+val value = someValue match {     // pattern matching
+      case Some(v) => v
+      case None => 0.0
+    }
+
+
    +
  • Option is more than just a replacement of null, its also a collection.
  • +
+
    Some(10) filter { _ == 10}
+    Some(Some(10)) flatMap { _ map { _ + 10}}
+  var newValue1 = 0
+    Some(20) foreach { newValue1 = _}
+
+
    +
  • flatMap of Options will filter out all Nones and keep the Somes
  • +
+
val list = List(1, 2, 3, 4, 5)
+val result = list.flatMap(it => if (it % 2 == 0) Some(it) else None)
+
+
    +
  • Using "for comprehension"
  • +
+
    val values = List(Some(10), Some(20), None, Some(15))
+    val newValues = for {
+      someValue <- values
+      value <- someValue
+    } yield value
+
+

Java Interop

+

Scala can implicitly convert from a Scala collection type into a Java collection type.

+
import scala.collection.JavaConversions._
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Scala/Scala_Database_Access/index.html b/Scala/Scala_Database_Access/index.html new file mode 100644 index 0000000..2713ea7 --- /dev/null +++ b/Scala/Scala_Database_Access/index.html @@ -0,0 +1,3325 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scala Database Access - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Scala/Scala_Design_Patterns/index.html b/Scala/Scala_Design_Patterns/index.html new file mode 100644 index 0000000..0108f50 --- /dev/null +++ b/Scala/Scala_Design_Patterns/index.html @@ -0,0 +1,3659 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scala Design Patterns - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Scala Design Patterns

+ +

Create a new project from template

+

Use the “sbt new” command, providing the name of the template. For example, “$ sbt new akka/hello-akka.g8”. +You can find a list of templates here.

+

Or download from Scala Project Templates

+

Static Factory

+
trait Animal
+class Bird extends Animal
+class Mammal extends Animal
+class Fish extends Animal
+
+object Animal {
+  def apply(animal: String): Animal = animal.toLowerCase match {
+    case "bird" => new Bird
+    case "mammal" => new Mammal
+    case "fish" => new Fish
+    case x: String => throw new RuntimeException(s"Unknown animal: $x")
+  }
+}
+
+

Algebraic Data Types and Pattern Matching

+
    +
  • Goal: translate data descriptions into code
  • +
  • Model data with logical ors and logical ands
  • +
  • Two patterns: product types (and) sum types (or)
  • +
  • Product type: A has a B and C
  • +
  • Sum type: A is a B or C
  • +
  • Sum and product together make algebraic data types
  • +
+
// A has a B and C
+case class A(b: B, c: C)
+
+// A is a B or C
+sealed trait A
+case class B() extends A
+case class C() extends A
+
+

They have only data and do not contain any functionality on top of this data as normal classes would.

+
sealed trait Shape
+case class Circle(radius: Double) extends Shape
+case class Rectangle(height: Double, width: Double) extends Shape
+
+object Shape {
+  def area(shape: Shape): Double =
+    shape match {
+      case Circle(Point(x, y), radius) => Math.PI * Math.pow(radius, 2)   // use pattern matching to process
+      case Rectangle(_, h, w) => h * w
+    }
+}
+
+

Stackable Traits

+
abstract class StringWriter {
+  def write(data: String): String
+}
+
+class BasicStringWriter extends StringWriter {
+  override def write(data: String): String =
+    s"Writing the following data: ${data}"
+}
+
+trait CapitalizingStringWriter extends StringWriter {
+  abstract override def write(data: String): String = {
+    super.write(data.split("\\s+").map(_.capitalize).mkString(" "))
+  }
+}
+
+trait UppercasingStringWriter extends StringWriter {
+  abstract override def write(data: String): String = {
+    super.write(data.toUpperCase)
+  }
+}
+
+object Example {
+  def main(args: Array[String]): Unit = {
+    val writer1 = new BasicStringWriter with UppercasingStringWriter with CapitalizingStringWriter
+    System.out.println(s"Writer 1: '${writer1.write("we like learning scala!")}'")
+  }
+}
+
+

Stackable traits order of execution

+

Stackable traits are always executed from the right mixin to the left. +Sometimes, however, if we only get output and it doesn't depend on what is passed to the method, we simply end up with method calls on a stack, which then get evaluated and it will appear as if things are applied from left to right.

+

Components / Cake Pattern

+

https://jonasboner.com/real-world-scala-dependency-injection-di/

+
// Service Interfaces and Component Definitions
+
+trait OnOffDeviceComponent {
+  val onOff: OnOffDevice  // abstract val
+
+  trait OnOffDevice {
+    def on: Unit
+    def off: Unit
+  }
+}
+
+trait SensorDeviceComponent {
+  val sensor: SensorDevice
+
+  trait SensorDevice {
+    def isCoffeePresent: Boolean
+  }
+}
+
+// =======================
+// Component / Service Implementations
+
+trait OnOffDeviceComponentImpl extends OnOffDeviceComponent {
+  class Heater extends OnOffDevice {
+    def on = println("heater.on")
+    def off = println("heater.off")
+  }
+}
+
+trait SensorDeviceComponentImpl extends SensorDeviceComponent {
+  class PotSensor extends SensorDevice {
+    def isCoffeePresent = true
+  }
+}
+
+// =======================
+// Component declaring two dependencies that it wants injected
+trait WarmerComponentImpl {
+  this: SensorDeviceComponent with OnOffDeviceComponent =>     // Use of self-type for composition
+  class Warmer {
+    def trigger = {
+      if (sensor.isCoffeePresent) onOff.on
+      else onOff.off
+    }
+  }
+}
+
+// =======================
+// Instantiation (and configuration) of the services in the ComponentRegistry module
+
+object ComponentRegistry extends
+  OnOffDeviceComponentImpl with
+  SensorDeviceComponentImpl with
+  WarmerComponentImpl {
+
+  val onOff = new Heater      // all instantiations in one spot; can be easily be replaced by e.g. mocks
+  val sensor = new PotSensor
+  val warmer = new Warmer
+}
+
+// =======================
+val warmer = ComponentRegistry.warmer
+warmer.trigger
+
+

Type Classes (using context-bound type parameters)

+
    +
  • Ad-hoc polymorphism
  • +
  • Break free from your class oppressors!
  • +
  • Concerns that cross class hierarchy e.g. serialize to JSON
  • +
  • Common behaviour without (useful) common type
  • +
  • Abstract behaviour to a type class
  • +
  • Can implement type class instances in ad-hoc manner
  • +
+
// Define some behavior in terms of operations that a type must support in order to be considered a member of the type class.
+trait Number[T] {
+  def plus(x: T, y: T): T
+  def divide(x: T, y: Int): T
+}
+
+// Define the default type class members in the companion object of the trait
+object Number {
+
+  implicit object DoubleNumber extends Number[Double] {    // note the implicit
+    override def plus(x: Double, y: Double): Double = x + y
+    override def divide(x: Double, y: Int): Double = x / y
+  }
+}
+
+object Stats {
+
+//  older pattern with implicit parameter
+//  def mean[T](xs: Vector[T])(implicit ev: Number[T]): T =   // note the implicit
+//    ev.divide(xs.reduce(ev.plus(_, _)), xs.size)
+
+  def mean[T: Number](xs: Vector[T]): T =        // note the context bound
+    implicitly[Number[T]].divide(
+      xs.reduce(implicitly[Number[T]].plus(_, _)),     // retrieve the evidence via implicitly[]
+      xs.size
+    )
+}
+
+

Visitor Pattern

+
abstract class Element(text: String) {
+  def accept(visitor: Visitor)
+}
+
+case class Title(text: String) extends Element(text) {
+  override def accept(visitor: Visitor): Unit = {
+    visitor.visit(this)
+  }
+}
+
+case class Text(text: String) extends Element(text) {
+  override def accept(visitor: Visitor): Unit = {
+    visitor.visit(this)
+  }
+}
+
+class Document(parts: List[Element]) {
+  def accept(visitor: Visitor): Unit = {
+    parts.foreach(p => p.accept(visitor))
+  }
+}
+
+trait Visitor {
+  def visit(element: Element)
+}
+
+class VisitorImpl1 extends Visitor {
+  override def visit(element: Element): Unit = {
+    element match {
+      case Title(text) => ???
+      case Text(text) => ???
+   //...
+   }
+  }
+}
+
+

Configuration

+
import com.typesafe.config.ConfigFactory
+
+trait AppConfigComponent {
+
+  val appConfigService: AppConfigService
+
+  class AppConfigService() {
+    //-Dconfig.resource=production.conf for overriding
+    private val conf = ConfigFactory.load()
+    private val appConf = conf.getConfig("job-scheduler")
+    private val db = appConf.getConfig("db")
+
+    val configPath = appConf.getString("config-path")
+    val configExtension = appConf.getString("config-extension")
+    val workers = appConf.getInt("workers")
+
+    val dbConnectionString = db.getString("connection-string")
+    val dbUsername = db.getString("username")
+    val dbPassword = db.getString("password")
+  }
+}
+
+

Memoization

+
import scala.collection.mutable.Map
+
+trait Memoizer {
+
+  def memo[X, Y](f: X => Y): (X => Y) = {
+    val cache = Map[X, Y]()
+    (x: X) => cache.getOrElseUpdate(x, f(x))
+  }
+}
+
+

Using scalaz:

+
val memoScalaz: String => String = Memo.mutableHashMapMemo {
+  func
+}
+
+

Pimp my Library Pattern

+

The pimp my library design pattern is really similar to extension methods in C#.

+
package object pimp {
+
+  implicit class StringExtensions(val s: String) extends AnyVal {
+
+    def isAllUpperCase: Boolean =
+      (0 to s.size - 1).find {
+        case index =>
+          !s.charAt(index).isUpper
+      }.isEmpty
+
+  }
+}
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Scala/Scala_Generalities/index.html b/Scala/Scala_Generalities/index.html new file mode 100644 index 0000000..7c4a3a9 --- /dev/null +++ b/Scala/Scala_Generalities/index.html @@ -0,0 +1,3371 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scala (Generalities) - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Scala (Generalities)

+ +

Main Features of Scala

+
    +
  • All types are objects
  • +
  • Type inference
  • +
  • Nested Functions
  • +
  • Functions are objects
  • +
  • Domain specific language (DSL) support
  • +
  • Traits
  • +
  • Closures
  • +
  • Concurrency support inspired by Erlang
  • +
+

Tools and Frameworks

+

REPL https://ammonite.io/

+

https://scalafiddle.io/

+ +

https://typelevel.org/

+

Install

+
    +
  • Need to have Java Software Development Kit (SDK) installed
  • +
+
java -version
+
+
export JAVA_HOME=/usr/local/java-current
+export PATH=$PATH:$JAVA_HOME/bin/
+
+

https://www.scala-lang.org/download/

+

Compilation

+
scalac HelloWorld.scala  // produces HelloWorld.class
+scala -classpath . HelloWorld
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Scala/Scala_Language/index.html b/Scala/Scala_Language/index.html new file mode 100644 index 0000000..4457b85 --- /dev/null +++ b/Scala/Scala_Language/index.html @@ -0,0 +1,4494 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scala Language - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Scala Language

+ + + +

Some examples are derived from Scala Koans.

+

Basics

+

Style

+

Class Names - For all class names, the first letter should be in Upper Case. If several words are used to form a name of the class, each inner word's first letter should be in Upper Case.

+

class MyFirstScalaClass

+

Method Names - All method names should start with a Lower Case letter. If multiple words are used to form the name of the method, then each inner word's first letter should be in Upper Case.

+

def myMethodName()

+

Program File Name - Name of the program file should exactly match the object name. When saving the file you should save it using the object name (Remember Scala is case-sensitive) and append ".scala" to the end of the name. If the file name and the object name do not match your program will not compile.

+

Assume 'HelloWorld' is the object name: the file should be saved as 'HelloWorld.scala'.

+

Packages

+
package pkg   // at start of file
+package pkg { ... } // bracket style
+
+

Imports

+
import scala.collection._                 // wildcard import. When importing all the names of a package or class, one uses the underscore character (_) instead of the asterisk (*).
+import scala.collection.Vector              // one class import
+import scala.collection.{Vector, Sequence} // selective import. Multiple classes can be imported from the same package by enclosing them in curly braces
+import scala.collection.{Vector => Vec28} // renaming import.
+import java.util.{Date => _, _}             // import all from java.util except Date.
+
+

All classes from the java.lang package are imported by default. The Predef object provides definitions that are accessible in all Scala compilation units without explicit qualification:

+
    +
  • immutable Map, Set, List, ::, Nil, print, println, assert, assume, require, ensuring
  • +
+
import scala.collection.mutable.HashMap               // Mutable collections must be imported.
+import scala.collection.immutable.{TreeMap, TreeSet}  // So are specialized collections.
+
+

Application Entry Point

+
object HelloWorld {
+    def main(args: Array[String]) {
+        println("Hello, world!")
+    }
+}
+
+

Blocks

+

You can combine expressions by surrounding them with {}. We call this a block. +The result of the last expression in the block is the result of the overall block, too.

+
println({
+  val x = 1 + 1
+  x + 1
+}) // 3
+
+

Variables and Values

+
var x = 5 // variable
+val x = 5 // immutable value / "const"
+var x: Double = 5 // explicit type
+println(x)
+
+

A lazy val is assignment that will not evaluated until it is called. Note there is no lazy var

+
lazy val a = {heavymath(); 19}
+
+

Literals

+
val a = 2  // int
+val b = 31L     // long
+val c = 0x30B   // hexadecimal
+val d = 3f  // float
+val e = 3.22d // double
+val f = 93e-9
+val g = 'a'   // character
+val h = '\u0061'  // unicode for a
+val i = '\141'   // octal for a
+val j = '\"'  // escape sequences
+val k = '\\'
+val s = "To be or not to be"   // string
+s.charAt(0)
+val s2 = """An apple a day
+keeps the doctor away"""  // multi-lines string
+s2.split('\n')
+val s3 = """An apple a day
+           |keeps the doctor away"""  // Multiline String literals can use | to specify the starting position of subsequent lines, then use stripMargin to remove the surplus indentation.
+s3.stripMargin
+
+

Enumerations

+
object Planets extends Enumeration {
+  val Mercury = Value
+  val Venus = Value
+  val Earth = Value
+  val Mars = Value
+  val Jupiter = Value
+  val Saturn = Value
+  val Uranus = Value
+  val Neptune = Value
+  val Pluto = Value
+}
+
+Planets.Mercury.id
+Planets.Mercury.toString //How does it get the name? by Reflection.
+
+object GreekPlanets extends Enumeration {
+  val Mercury = Value(1, "Hermes")   // enumeration with your own index and/or your own Strings
+  val Venus = Value(2, "Aphrodite")
+  //Fun Fact: Tellus is Roman for (Mother) Earth
+  val Earth = Value(3, "Gaia")
+  val Mars = Value(4, "Ares")
+  val Jupiter = Value(5, "Zeus")
+  val Saturn = Value(6, "Cronus")
+  val Uranus = Value(7, "Ouranus")
+  val Neptune = Value(8, "Poseidon")
+  val Pluto = Value(9, "Hades")
+}
+
+

Common Data Structures

+
(1,2,3)                  // tuple literal. (Tuple3)
+var (x,y,z) = (1,2,3)  // destructuring bind: tuple unpacking via pattern matching.
+// BAD var x,y,z = (1,2,3) // hidden error: each assigned to the entire tuple.
+
+val tuple = ("apple", 3) // mixed type tuple
+tuple._1
+tuple._2
+tuple.swap
+
+
var xs = List(1,2,3)  // list (immutable).
+xs(2)                  // paren indexing
+1 :: List(2,3)    // cons (create a new list by prepending the element).
+
+1 to 5                   // Range sugar. Same as `1 until 6`
+1 to 10 by 2
+Range(1, 10, 2)    // Range does not include the last item, even in a step increment
+Range(1, 9, 2).inclusive
+
+
()        // (empty parens) sole member of the Unit type (like C/Java void).
+
+

Control Constructs

+
if (check) happy else sad // conditional.
+if (check) happy            //
+if (check) happy else () // same as above
+while (x < 5) { println(x); x += 1} // while loop.
+do { println(x); x += 1} while (x < 5) // do while loop.
+
+for (x <- xs if x%2 == 0) yield x*10  // for comprehension with guard
+xs.filter(_%2 == 0).map(_*10)       // same as filter/map
+for ((x,y) <- xs zip ys) yield x*y    // for comprehension: destructuring bind
+(xs zip ys) map { case (x,y) => x*y } // same as
+for (x <- xs; y <- ys) yield x*y      // for comprehension: cross product. Later generators varying more rapidly than earlier ones
+xs flatMap {x => ys map {y => x*y}}   // same as
+for (x <- xs; y <- ys) {
+  println("%d/%d = %.1f".format(x, y, x/y.toFloat))  // for comprehension: imperative-ish
+}
+for (i <- 1 to 5) {      // for comprehension: iterate including the upper bound
+  println(i)
+}
+for (i <- 1 until 5) {     // for comprehension: iterate omitting the upper bound
+  println(i)
+}
+
+import scala.util.control.Breaks._  // break
+breakable {
+  for (x <- xs) {
+    if (Math.random < 0.1) break
+  }
+}
+
+

Formatting and Interpolation

+
val helloMessage = "Hello World"
+s"Application $helloMessage"  // string interpolation; can include expressions which can include numbers and strings
+// use `f` prefix before the string instead of an `s` for sprintf formatting
+
+

Functions

+

Scala is a functional language in the sense that every function is a value and every value is an object so ultimately every function is an object. +Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying.

+
def add(x: Int, y: Int): Int = x + y   // the return type is declared after the parameter list and a colon
+
+// GOOD def f(x: Any) = println(x)
+// BAD  def f(x) = println(x)   // syntax error: need types for every arg.
+
+def f(x: Int) = {       // inferred return type
+  val square = x*x
+  square.toString
+  } // The last expression in the body is the method’s return value. (Scala does have a return keyword, but it’s rarely used.)
+
+// BAD def f(x: Int) { x*x }  hidden error: without = it’s a Unit-returning procedure; causes havoc
+
+// When performing recursion, the return type on the method is mandatory!
+
+
    +
  • Backticks for reserved keywords and identifiers with a space (rare)
  • +
+
def `put employee on probation`(employee: Employee) = {
+       new Employee(employee.`first name`, employee.`last name`, "Probation")
+    }
+
+

Multiple parameter lists or none at all

+
def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier
+def name: String = System.getProperty("name")
+
+

Procedures

+
def foo(x: Int) { //Note: No `=`; returns Unit
+      print(x.toString)
+    }
+def foo(x: Int): Unit =  print(x.toString)  // or
+
+

Convention (not required for the compiler) states that if you a call a method that returns a Unit / has a side effect, invoke that method with empty parenthesis, other leave the parenthesis out

+
def performSideEffect():Unit = System.currentTimeMillis
+performSideEffect()
+
+

Default and named parameters

+
def addColorsWithDefaults(red: Int = 0, green: Int = 0, blue: Int = 0) = {
+  (red, green, blue)
+}
+
+me.addColors(blue = 40)
+
+

Variable Length Arguments

+
def sum(args: Int*) = args.reduceLeft(_+_)    // varargs. must be last arg
+
+def capitalizeAll(args: String*) = {
+      args.map { arg =>
+        arg.capitalize
+      }
+    }
+
+capitalizeAll("rarity", "applejack")
+
+

If you want a collection expanded into a vararg, add :_*

+
def repeatedParameterMethod(x: Int, y: String, z: Any*) = {
+    "%d %ss can give you %s".format(x, y, z.mkString(", "))
+  }
+
+repeatedParameterMethod(3, "egg", List("a delicious sandwich", "protein", "high cholesterol"):_*) should be(__)
+
+

Tail recursion

+

As a precaution, the helpful @tailrec annotation will throw a compile time if a method is not tail recursive, +meaning that the last call and only call of the method is the recursive method. Scala optimizes recursive calls +to a loop from a stack

+
import scala.annotation.tailrec // importing annotation!
+@tailrec      //  compiler will check that the function is tail recursive
+def factorial(i: BigInt): BigInt = {
+      @tailrec
+      def fact(i: BigInt, accumulator: BigInt): BigInt = {  // methods can be placed inside in methods; return type is obligatory
+        if (i <= 1)
+          accumulator
+        else
+          fact(i - 1, i * accumulator)
+      }
+      fact(i, 1)
+    }
+
+factorial(3)
+
+

Infix, Postfix and Prefix Notations; Operators

+
object FrenchDate {
+    def main(args: Array[String]) {
+        val now = new Date
+        val df = getDateInstance(LONG, Locale.FRANCE)
+    println(df format now)       // Methods taking one argument can be used with an infix syntax. Equivalent to df.format(now)
+    }
+}
+
+

1 + 2 * 3 / x consists exclusively of method calls, because it is equivalent to the following expression: (1).+(((2).*(3))./(x)) +This also means that +, *, etc. are valid identifiers in Scala.

+

Infix Operators do NOT work if an object has a method that takes two parameters.

+
 val g: Int = 31
+ val s: String = g toHexString  // Postfix operators work if an object has a method that takes no parameters
+
+

Prefix operators work if an object has a method name that starts with unary_

+
class Stereo {
+      def unary_+ = "on"
+      def unary_- = "off"
+    }
+
+val stereo = new Stereo
++stereo   // it is on
+
+

Methods with colons are right-associative, that means the object that a method is on will be on the right and the method parameter will be on the left

+
class Foo (y:Int) {
+      def ~:(n:Int) = n + y + 3
+    }
+
+val foo = new Foo(9)
+10 ~: foo
+foo.~:(10)  // same as
+
+

Anonymous Functions

+
def lambda = (x: Int) => x + 1
+
+// other variants
+def lambda2 = { x: Int => x + 1 }
+val lambda3 = new Function1[Int, Int] {
+      def apply(v1: Int): Int = v1 + 1
+    }
+
+val everything = () => 42        // without parameter
+val add = (x: Int, y: Int) => x + y    // multiple parameters
+
+(1 to 5).map(_*2)                // underscore notation.
+(1 to 5) map (_*2)        // same with infix sugar.
+(1 to 5).reduceLeft( _+_ )      // underscores are positionally matched 1st and 2nd args.
+(1 to 5).map( x => x*x )      // to use an arg twice, have to name it.
+(1 to 5).map { x => val y = x*2; println(y); y } // block style returns last expression.
+(1 to 5) filter {_%2 == 0} map {_*2}            // pipeline style (works with parens too).
+
+// GOOD (1 to 5).map(2*)
+// BAD (1 to 5).map(*2)                         // anonymous function: bound infix method. Use 2*_ for sanity’s sake instead.
+
+def compose(g: R => R, h: R => R) = (x:R) => g(h(x))
+val f = compose({_*2}, {_-1})     // anonymous functions: to pass in multiple blocks, need outer parens.
+
+

Passing anonymous functions as parameter:

+
def makeWhatEverYouLike(xs: List[String], func: String => String) = {
+      xs map func
+    }
+
+

Function returning another function using an anonymous function:

+
def add(x: Int) = (y:Int) => x + y
+
+

Function Values:

+
object Timer {
+    def oncePerSecond(callback: () => Unit) {        // () => T is a Function type that takes a Unit type. Unit is known as 'void' to a Java programmer.
+        while (true) { callback(); Thread sleep 1000 }
+    }
+
+    def timeFlies() {
+        println("time flies like an arrow...")
+    }
+
+    def main(args: Array[String]) {
+        oncePerSecond(timeFlies)       // function value; could also be () => timeFlies()
+    }
+}
+
+

By-name parameter

+

This is used extensively in scala to create blocks.

+
    def calc(x: => Int): Either[Throwable, Int] = {   //x is a call by name parameter; delayed execution of x
+      try {
+        Right(x)
+      } catch {
+        case b: Throwable => Left(b)
+      }
+    }
+
+    val y = calc {                                    //This looks like a natural block
+      println("Here we go!")                          //Some superfluous call
+      49 + 20
+    }
+
+

By name parameters can also be used with an Object and apply to make interesting block-like calls

+
object PigLatinizer {
+      def apply(x: => String) = x.tail + x.head + "ay"
+    }
+
+val result = PigLatinizer {
+      val x = "pret"
+      val z = "zel"
+      x ++ z //concatenate the strings
+    }
+
+

Closures

+
var incrementer = 1
+
+def closure = {
+  x: Int => x + incrementer
+}
+
+

Currying

+
val zscore = (mean: R, sd: R) => (x:R) => (x-mean)/sd  // currying, obvious syntax.
+def zscore(mean: R, sd: R) = (x: R) => (x-mean)/sd         // currying, obvious syntax
+def zscore(mean: R, sd: R)(x: R) = (x-mean)/sd          // currying, sugar syntax. but then:
+val normer = zscore(7, 0.4) _                          // need trailing underscore to get the partial, only for the sugar version.
+def mapmake[T](g: T => T)(seq: List[T]) = seq.map(g)  // generic type.
+
+def multiply(x: Int, y: Int) = x * y
+val multiplyCurried = (multiply _).curried
+multiply(4, 5)
+multiplyCurried(3)(2)
+
+

Partial Applications

+
def adder(m: Int, n: Int) = m + n
+val add2 = adder(2, _:Int)  // You can partially apply any argument in the argument list, not just the last one.
+add2(3)    // which is 5
+
+val add3 = adder _    // underscore to convert from a function to a lambda
+adder(1, 9)
+add3(1, 9)
+
+

Partial Functions

+
val doubleEvens: PartialFunction[Int, Int] = new PartialFunction[Int, Int] {   // full declaration
+      //States that this partial function will take on the task
+      def isDefinedAt(x: Int) = x % 2 == 0
+
+      //What we do if this does partial function matches
+      def apply(v1: Int) = v1 * 2
+    }
+
+val tripleOdds: PartialFunction[Int, Int] = {
+      case x: Int if (x % 2) != 0 => x * 3    // syntaxic sugar (usual way)
+    }
+
+val whatToDo = doubleEvens orElse tripleOdds    // combine the partial functions together: OrElse
+
+val addFive = (x: Int) => x + 5
+val whatToDo = doubleEvens orElse tripleOdds andThen addFive  // chain (partial) functions together: andThen
+
+

Classes, Objects, and Traits

+
class C(x: R)                     // constructor params - x is only available in class body
+class C(val x: R)      // c.x constructor params - automatic public (immutable) member defined
+class D(var x: R)       // you can define class with var or val parameters
+
+class C(var x: R) {
+  assert(x > 0, "positive please")  // constructor is class body
+  var y = x                         // declare a public member
+  val readonly = 5                  // declare a gettable but not settable member
+  private var secret = 1            // declare a private member
+  def this = this(42)               // alternative constructor
+}
+
+new{ ... } // anonymous class
+abstract class D { ... } // define an abstract(non-createable) class.
+class C extends D { ... } // define an inherited class. Class hierarchy is linear, a class can only extend from one parent class
+class C(x: R) extends D(x) // inheritance and constructor params. (wishlist: automatically pass-up params by default)
+// A class can be placed inside another class
+object O extends D { ... } // define a singleton.
+
+trait T { ... }    // traits. See below.
+class C extends T { ... }
+class C extends D with T { ... }
+
+// interfaces-with-implementation. no constructor params. mixin-able.
+trait T1; trait T2
+class C extends T1 with T2          // multiple traits.
+class C extends D with T1 with T2 // parent class and (multiple) trait(s).
+class C extends D { override def f = ...} // must declare method overrides.
+
+var c = new C(4)  // Instantiation
+//BAD new List[Int]
+//GOOD List(1,2,3)  // Instead, convention: callable factory shadowing the type
+
+classOf[String] // class literal.
+classOf[String].getCanonicalName
+classOf[String].getSimpleName
+val zoom = "zoom"
+zoom.getClass == classOf[String]
+
+x.isInstanceOf[String] // type check (runtime)
+x.asInstanceOf[String] // type cast (runtime)
+x: String    // compare to parameter ascription (compile time)
+
+

Methods

+
class Complex(real: Double, imaginary: Double) {
+    def re = real       // return type inferred automatically by the compiler
+    def im = imaginary  // methods without arguments
+    def print(): Unit = println(s"$real + i * $imaginary")
+ override def toString() = "" + re + (if (im < 0) "" else "+") + im + "i"  // override methods inherited from a super-class
+}
+
+

Asserts and Contracts

+

Asserts take a boolean argument and can take a message.

+
assert(true) // should be true
+assert(true, "This should be true")
+
+
def addNaturals(nats: List[Int]): Int = {
+  require(nats forall (_ >= 0), "List contains negative numbers")
+  nats.foldLeft(0)(_ + _)
+} ensuring(_ >= 0)
+
+

Path-dependent Classes

+

When a class is instantiated inside of another object, it belongs to the instance. This is a path dependent type. Once established, it cannot be placed inside of another object

+
case class Board(length: Int, height: Int) {
+  case class Coordinate(x: Int, y: Int)
+}
+
+val b1 = Board(20, 20)
+val b2 = Board(30, 30)
+val c1 = b1.Coordinate(15, 15)
+val c2 = b2.Coordinate(25, 25)
+// val c1 = c2  won't work
+
+

Use A#B for a Java-style inner class:

+
class Graph {
+  class Node {
+    var connectedNodes: List[Graph#Node] = Nil   // accepts Nodes from any Graph
+    def connectTo(node: Graph#Node) {
+      if (connectedNodes.find(node.equals).isEmpty) {
+        connectedNodes = node :: connectedNodes
+      }
+    }
+  }
+  var nodes: List[Node] = Nil
+  def newNode: Node = {
+    val res = new Node
+    nodes = res :: nodes
+    res
+  }
+}
+
+

Companion Objects

+

Static members (methods or fields) do not exist in Scala. Rather than defining static members, the Scala programmer declares these members in singleton objects, that is a class with a single instance.

+
object TimerAnonymous {
+    def oncePerSecond(callback: () => Unit) {
+        while (true) { callback(); Thread sleep 1000 }
+    }
+    def main(args: Array[String]) {
+        oncePerSecond(() => println("time flies like an arrow..."))
+    }
+}
+
+
    +
  • An object that has the same name as class is called a companion object, it is used to contain factories for the class that it complements.
  • +
  • A companion object can also store shared variables and values for every instantiated class to share.
  • +
  • A companion object can see private values and variables of the instantiated object
  • +
+

Apply Method

+

The apply method is a magical method in Scala.

+
class Employee (val firstName:String, val lastName:String)
+
+object Employee {
+ def apply(firstName:String, lastName:String) = new Employee(firstName, lastName)  // would also work in a class, but rarer
+}
+
+val a = Employee("John", "Doe")
+// is equivalent to
+var b = Employee.apply("John", "Doe")
+
+

Case Classes

+
    +
  • The new keyword is not mandatory to create instances of these classes (i.e. one can write Const(5) instead of new Const(5)),
  • +
  • Getter functions are automatically defined for the constructor parameters (i.e. it is possible to get the value of the v constructor parameter of some instance c of class Const just by writing c.v),
  • +
  • Default definitions for methods equals and hashCode are provided, which work on the structure of the instances and not on their identity,
  • +
  • A default definition for method toString is provided, and prints the value in a source form (e.g. the tree for expression x+1 prints as Sum(Var(x),Const(1))),
  • +
  • Instances of these classes can be decomposed through pattern matching
  • +
+
case class Person(first: String, last: String, age: Int = 0)  // Case classes can have default and named parameters
+val p1 = Person("Fred", "Jones")    // new is optional
+val p2 = new Person("Fred", "Jones")
+p1 == p2         // true
+p1.hashCode == p2.hashCode    // true
+p1 eq p2         // false
+val p3 = p2.copy(first = "Jane")  // copy the case class but change the name in the copy
+
+
case class Dog(var name: String, breed: String)   // Case classes can have mutable properties - potentially unsafe
+
+

Case classes can be disassembled to their constituent parts as a tuple:

+
val parts = Person.unapply(p1).get // returns Option[T]
+parts._1
+parts._2
+
+

Algebraic data type

+
sealed trait Tree    // or abstract class
+final case class Sum(l: Tree, r: Tree) extends Tree
+final case class Var(n: String) extends Tree
+final case class Const(v: Int) extends Tree
+
+

Pattern Matching

+

{ case "x" => 5 } defines a partial function which, when given the string "x" as argument, returns the integer 5, and fails with an exception otherwise.

+
type Environment = String => Int  // the type Environment can be used as an alias of the type of functions from String to Int
+
+def eval(t: Tree, env: Environment): Int = t match {
+    case Sum(l, r) => eval(l, env) + eval(r, env)
+    case Var(n) => env(n)
+    case Const(v) => v
+}
+
+def derive(t: Tree, v: String): Tree = t match {
+    case Sum(l, r) => Sum(derive(l, v), derive(r, v))
+    case Var(n) if (v == n) => Const(1)                  // guard, an expression following the if keyword.
+    case _ => Const(0)                                   // wild-card, written _, which is a pattern matching any value, without giving it a name.
+}
+
+
// GOOD (xs zip ys) map { case (x,y) => x*y }
+// BAD (xs zip ys) map( (x,y) => x*y ) // use case in function args for pattern matching.
+// BAD
+val v42 = 42
+Some(3) match {
+  case Some(v42) => println("42")
+  case _ => println("Not 42")
+} // “v42” is interpreted as a name matching any Int value, and “42” is printed.
+// GOOD
+val v42 = 42
+Some(3) match {
+  case Some(`v42`) => println("42")
+  case _ => println("Not 42")
+} // ”`v42`” with backticks is interpreted as the existing val v42, and “Not 42” is printed.
+// GOOD
+val UppercaseVal = 42
+Some(3) match {
+  case Some(UppercaseVal) => println("42")
+  case _ => println("Not 42")
+} // UppercaseVal is treated as an existing val, rather than a new pattern variable, because it starts with an uppercase letter.
+// Thus, the value contained within UppercaseVal is checked against 3, and “Not 42” is printed.
+
+

List Matching

+
val secondElement = List(1,2,3) match {
+      case x :: y :: xs => xs
+   case x :: Nil => x
+      case _ => 0
+    }
+
+

Regex

+
val MyRegularExpression = """a=([^,]+),\s+b=(.+)""".r     //.r turns a String to a regular expression
+expr match {
+      case (MyRegularExpression(a, b)) => a + b
+   }
+
+
import scala.util.matching.Regex
+
+val numberPattern: Regex = "[0-9]".r
+
+numberPattern.findFirstMatchIn("awesomepassword") match {
+  case Some(_) => println("Password OK")
+  case None => println("Password must contain a number")
+}
+
+

With groups:

+
val keyValPattern: Regex = "([0-9a-zA-Z-#() ]+): ([0-9a-zA-Z-#() ]+)".r
+
+for (patternMatch <- keyValPattern.findAllMatchIn(input))
+  println(s"key: ${patternMatch.group(1)} value: ${patternMatch.group(2)}")
+
+

Extractors (unapply)

+
class Car(val make: String, val model: String, val year: Short, val topSpeed: Short)
+
+object Car {                 // What is typical is to create a custom extractor in the companion object of the class.
+  def unapply(x: Car) = Some(x.make, x.model, x.year, x.topSpeed)   // returns an Option[T]
+}
+
+val Car(a, b, c, d) = new Car("Chevy", "Camaro", 1978, 120)   // assign values to a .. d
+
+val x = new Car("Chevy", "Camaro", 1978, 120) match {    // pattern matching
+  case Car(s, t, _, _) => (s, t)         // _ for variables we don't care about.
+  case _ => ("Ford", "Edsel")           // fallback
+}
+
+
    +
  • As long as the method signatures aren't the same, you can have an many unapply methods as you want in the same class / object.
  • +
  • When you create a case class, it automatically can be used with pattern matching since it has an extractor.
  • +
+

Value Class

+

Avoid allocating runtime objects.

+
class Wrapper(val underlying: Int) extends AnyVal {
+  def foo: Wrapper = new Wrapper(underlying * 19)
+}
+
+

It has a single, public val parameter that is the underlying runtime representation. The type at compile time is Wrapper, but at runtime, the representation is an Int. A value class can define defs, but no vals, vars, or nested traitss, classes or objects

+

A value class can only extend universal traits and cannot be extended itself. A universal trait is a trait that extends Any, only has defs as members, and does no initialization. Universal traits allow basic inheritance of methods for value classes, but they incur the overhead of allocation.

+

Traits

+

Apart from inheriting code from a super-class, a Scala class can also import code from one or several traits i.e. interfaces which can also contain code. +In Scala, when a class inherits from a trait, it implements that traits's interface, and inherits all the code contained in the trait.

+
trait Ord {
+    def < (that: Any): Boolean                              // The type Any which is used above is the type which is a super-type of all other types in Scala
+    def <=(that: Any): Boolean = (this < that) || (this == that)
+    def > (that: Any): Boolean = !(this <= that)
+    def >=(that: Any): Boolean = !(this < that)
+}
+
+class Date(y: Int, m: Int, d: Int) extends Ord {
+    def year = y
+    def month = m
+    def day = d
+    override def toString(): String = year + "-" + month + "-" + day
+
+    override def equals(that: Any): Boolean =
+        that.isInstanceOf[Date] && {
+        val o = that.asInstanceOf[Date]
+        o.day == day && o.month == month && o.year == year
+    }
+
+    def <(that: Any): Boolean = {    // The trait declare the type (e.g. method), where a concrete implementer will satisfy the type
+        if (!that.isInstanceOf[Date])
+            error("cannot compare " + that + " and a Date")
+        val o = that.asInstanceOf[Date](year < o.year) ||
+            (year == o.year && (month < o.month ||
+            (month == o.month && day < o.day    )))
+    }
+}
+
+
    +
  • +

    Traits can have concrete implementations that can be mixed into concrete classes with its own state

    +
  • +
  • +

    Traits can be mixed in during instantiation!

    +
  • +
+
trait Logging {
+      var logCache = List[String]()
+
+      def log(value: String) = {
+        logCache = logCache :+ value
+      }
+
+      def log = logCache
+    }
+val a = new A("stuff") with Logging  // mixin traits during instantiation!
+a.log("I did something")
+a.log.size
+
+

Stackable Traits

+
abstract class IntQueue {
+  def get(): Int
+  def put(x: Int)
+}
+
+import scala.collection.mutable.ArrayBuffer
+
+class BasicIntQueue extends IntQueue {
+  private val buf = new ArrayBuffer[Int]
+  def get() = buf.remove(0)
+  def put(x: Int) { buf += x }
+}
+
+trait Doubling extends IntQueue {
+  abstract override def put(x: Int) { super.put(2 * x) }    // abstract override is necessary to stack traits
+}
+
+class MyQueue extends BasicIntQueue with Doubling   // could also mixin during instantiation
+
+val myQueue = new MyQueue
+myQueue.put(3)
+myQueue.get()
+
+
    +
  • More traits can be stacked one atop another, make sure that all overrides are labelled abstract override.
  • +
  • The order of the mixins are important. Traits on the right take effect first.
  • +
  • Traits are instantiated before a classes instantiation from left to right.
  • +
  • Linerization: the diamond inheritance problem is avoided since instantiations are tracked and will not allow multiple instantiations of the same parent trait
  • +
+

Classes versus Traits

+

Use classes:

+
    +
  • When a behavior is not going to be reused at all or in multiple places
  • +
  • When you plan to use your Scala code from another language, for example, if you are building a library that could be used in Java
  • +
+

Use traits:

+
    +
  • When a behavior is going to be reused in multiple unrelated classes.
  • +
  • When you want to define interfaces and want to use them outside Scala, for example Java. The reason is that the traits that do not have any implementations are compiled similar to interfaces.
  • +
+

Keyword List

+
    abstract
+    case
+    catch
+    class
+    def
+    do
+    else
+    extends
+    false
+    final
+    finally
+    for
+    forSome
+    if
+    implicit
+    import
+    lazy
+    match
+    new
+    Null
+    object
+    override
+    package
+    private
+    protected
+    return
+    sealed
+    super
+    this
+    throw
+    trait
+    Try
+    true
+    type
+    val
+    var
+    while
+    with
+    yield
+     -
+     :
+     =
+     =>
+    <-
+    <:
+    <%
+    >:
+    #
+    @
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Scala/Scala_Testing/index.html b/Scala/Scala_Testing/index.html new file mode 100644 index 0000000..d0e7031 --- /dev/null +++ b/Scala/Scala_Testing/index.html @@ -0,0 +1,3450 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scala Testing - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Scala Testing

+ + +

https://www.scalatest.org/

+

Writing TDD unit tests with scalatest

+

At a Glance

+

Examples

+
libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.6" % "test"
+
+
package com.acme.pizza
+
+import org.scalatest.FunSuite
+import org.scalatest.BeforeAndAfter
+
+class PizzaTests extends FunSuite with BeforeAndAfter {
+
+  var pizza: Pizza = _
+
+  before {
+    pizza = new Pizza
+  }
+
+  test("new pizza has zero toppings") {
+    assert(pizza.getToppings.size == 0)
+  }
+
+  test("adding one topping") {
+    pizza.addTopping(Topping("green olives"))
+    assert(pizza.getToppings.size === 1)
+  }
+
+  // mark that you want a test here in the future
+  test ("test pizza pricing") (pending)
+
+}
+
+

Styles

+

FunSuite

+
import org.scalatest.FunSuite
+class AddSuite extends FunSuite {
+  test("3 plus 3 is 6") {
+     assert((3 + 3) == 6)
+  }
+}
+
+

FlatSpec

+

The structure of this test is flat—like xUnit, but the test name can be written in specification style:

+
import org.scalatest.FlatSpec
+class AddSpec extends FlatSpec {
+  "Addition of 3 and 3" should "have result 6" in {
+    assert((3 + 3) == 0)
+  }
+}
+
+
import collection.mutable.Stack
+import org.scalatest._
+
+class ExampleSpec extends FlatSpec with Matchers {
+
+  "A Stack" should "pop values in last-in-first-out order" in {
+    val stack = new Stack[Int]
+    stack.push(1)
+    stack.push(2)
+    stack.pop() should be (2)
+    stack.pop() should be (1)
+  }
+
+  it should "throw NoSuchElementException if an empty stack is popped" in {
+    val emptyStack = new Stack[Int]
+    a [NoSuchElementException] should be thrownBy {
+      emptyStack.pop()
+    }
+  }
+}
+
+

FeatureSpec

+
import org.scalatest._
+
+class Calculator {
+  def add(a:Int, b:Int): Int = a + b
+}
+
+class CalcSpec extends FeatureSpec with GivenWhenThen {
+  info("As a calculator owner")
+  info("I want to be able add two numbers")
+  info("so I can get a correct result")
+  feature("Addition") {
+    scenario("User adds two numbers") {
+      Given("a calculator")
+      val calc = new Calculator
+      When("two numbers are added")
+      var result = calc.add(3, 3)
+      Then("we get correct result")
+       assert(result == 6)
+    }
+  }
+}
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Scala/Scala_Types/index.html b/Scala/Scala_Types/index.html new file mode 100644 index 0000000..b3ada74 --- /dev/null +++ b/Scala/Scala_Types/index.html @@ -0,0 +1,3610 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scala Types - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Scala Types

+ +

Type Refinement

+

Type Refinement = "subclassing without naming the subclass".

+
class Entity
+
+trait Persister {
+  def doPersist(e: Entity) = {
+    e.persistForReal()
+  }
+}
+
+// our refined instance (and type):
+val refinedMockPersister = new Persister {
+  override def doPersist(e: Entity) = ()
+}
+
+

Scala Types of Types

+

Generics

+
class Reference[T] {
+    private var contents: T = _             // _ represents a default value. This default value is 0 for numeric types, false for the Boolean type, () for the Unit type and null for all object types.
+    def set(value: T) { contents = value }
+    def get: T = contents
+}
+
+trait Cache[K, V] {
+      def get(key: K): V
+      def put(key: K, value: V)
+      def delete(key: K)
+    }
+
+def remove[K](key: K)  // function
+
+

Type Variance

+

Covariance +A allow you to set the your container to a either a variable with the same type or parent type.

+
class MyContainer[+A](a: A)(implicit manifest: scala.reflect.Manifest[A]) {
+      private[this] val item = a
+
+      def get = item
+
+      def contents = manifest.runtimeClass.getSimpleName
+    }
+
+    val fruitBasket: MyContainer[Fruit] = new MyContainer[Orange](new Orange())
+    fruitBasket.contents
+
+

Contravariance -A is the opposite of covariance

+

Declaring neither -/+, indicates invariance variance. You cannot use a superclass variable reference ("contravariant" position) or a subclass variable reference ("covariant" position) of that type.

+

Upper and Lower Type Bounds

+
abstract class Pet extends Animal { def name: String }
+
+class Cat extends Pet {
+  override def name: String = "Cat"
+}
+
+class PetContainer[P <: Pet](p: P) {
+  def pet: P = p   // The class PetContainer take a type parameter P which must be a subtype of Pet.
+}
+
+

Lower type bounds declare a type to be a supertype of another type. The term B >: A expresses that the type parameter B or the abstract type B refer to a supertype of type A.

+

Abstract Types

+
type R = Double // type alias
+
+
trait Container {
+  type T
+  val data: T
+
+  def compare(other: T) = data.equals(other)
+}
+
+class StringContainer(val data: String) extends Container {
+  override type T = String
+}
+
+

Generics vs Abstract Types

+

Generics:

+
    +
  • If you need just type instantiation. A good example is the standard collection classes.
  • +
  • If you are creating a family of types.
  • +
+

Abstract types:

+
    +
  • If you want to allow people to mix in types using traits.
  • +
  • If you need better readability in scenarios where both could be interchangeable.
  • +
  • If you want to hide the type definition from the client code.
  • +
+

Infix Type

+

We can make a type infix, meaning that a generic type with two type parameters can be displayed between two types. +The type specifier Pair[String,Int] can be written as String Pair Int.

+
class Pair[A, B](a: A, b: B)
+
+type ~[A,B] = Pair[A,B]
+val pairlist: List[String ~ Int]   // operator-like usage
+
+case class Item[T](i: T) {
+    def ~(j: Item[T]) = new Pair(this, j)  // creating an infix operator method to use with our infix type
+}
+
+(Item("a") ~ Item("b")).isInstanceOf[String ~ String]
+
+

ShapeLess

+

Structural Types

+
import scala.language.reflectiveCalls   // use reflection --> slow
+
+def onlyThoseThatCanPerformQuacks(quacker: {def quack:String}): String = {
+        "received message: %s".format(quacker.quack)
+      }
+
+type SpeakerAndMover = {def speak:String; def move(steps:Int, direction:String):String}  // with type aliasing
+
+

Self-type

+

Self-types are a way to declare that a trait must be mixed into another trait, even though it doesn’t directly extend it. That makes the members of the dependency available without imports.

+
trait User {
+  def username: String
+}
+
+trait Tweeter {
+  this: User =>  // reassign this
+  def tweet(tweetText: String) = println(s"$username: $tweetText")
+}
+
+class VerifiedTweeter(val username_ : String) extends Tweeter with User {  // We mixin User because Tweeter required it
+  def username = s"real $username_"
+}
+
+

Difference between a self type and extending a trait

+
    +
  • If you say that B extends A, then B is an A. When you use self-types, B requires an A.
  • +
+

There are two specific requirements that are created with self-types: +1. If B is extended, then you're required to mix-in an A. +1. When a concrete class finally extends/mixes-in these traits, some class/trait must implement A.

+
trait Wrong extends Tweeter {
+     def noCanDo = name        // does not compile
+}
+
+

If Tweeter was a subclass of User, there would be no error. In the code above, we required a User whenever Tweeter is used, however a User wasn't provided to Wrong, so we got an error.

+
    +
  • Self types allow you to define cyclical dependencies. For example, you can achieve this:
  • +
+
trait A { self: B => }
+trait B { self: A => }
+
+

Inheritance using extends does not allow that.

+
    +
  • Because self-types aren't part of the hierarchy of the required class they can be excluded from pattern matching, especially when you are exhaustively matching against a sealed hierarchy. This is convenient when you want to model orthogonal behaviors such as:
  • +
+
sealed trait Person
+trait Student extends Person
+trait Teacher extends Person
+trait Adult { this : Person => } // orthogonal to its condition
+
+val p : Person = new Student {}
+p match {
+  case s : Student => println("a student")
+  case t : Teacher => println("a teacher")
+} // that's it we're exhaustive
+
+

Implicits

+

Implicits wrap around existing classes to provide extra functionality

+
object MyPredef {   // usually in a companion object
+
+  class IntWrapper(val original: Int) {
+   def isOdd = original % 2 != 0
+   def isEven = !isOdd
+  }
+
+  implicit def thisMethodNameIsIrrelevant(value: Int) = new IntWrapper(value)
+}
+
+import MyPredef._
+//imported implicits come into effect within this scope
+19.isOdd
+
+// Implicits can be used to automatically convert one type to another
+import java.math.BigInteger
+implicit def Int2BigIntegerConvert(value: Int): BigInteger = new BigInteger(value.toString)
+def add(a: BigInteger, b: BigInteger) = a.add(b)
+add(3, 6)  // 3 and 6 are Int
+
+// Implicits function parameters
+def howMuchCanIMake_?(hours: Int)(implicit amount: BigDecimal, currencyName: String) = (amount * hours).toString() + " " + currencyName
+implicit var hourlyRate = BigDecimal(34.00)
+implicit val currencyName = "Dollars"
+howMuchCanIMake_?(30)
+
+

Default arguments though are preferred to Implicit Function Parameters.

+

Context-bound Types

+
def inspect[T : TypeTag](l: List[T]) = typeOf[T].typeSymbol.name.decoded
+val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil
+inspect(list)
+
+

equivalent to

+
def inspect[T](l: List[T])(implicit tt: TypeTag[T]) = tt.tpe.typeSymbol.name.decoded
+    val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil
+    inspect(list)
+
+

TypeTags can be used to determine a type used before it erased by the VM by using an implicit TypeTag argument.

+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Scala/Scaladoc/index.html b/Scala/Scaladoc/index.html new file mode 100644 index 0000000..1aeac21 --- /dev/null +++ b/Scala/Scaladoc/index.html @@ -0,0 +1,3453 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scaladoc - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Scaladoc

+ +

Scaladoc +Scaladoc Style Guide

+
 /** Start the comment here
+   * and use the left star followed by a
+   * white space on every line.
+   *
+   * Even on empty paragraph-break lines.
+   *
+   * Note that the * on each line is aligned
+   * with the second * in /** so that the
+   * left margin is on the same column on the
+   * first line and on subsequent ones.
+   *
+   * The closing Scaladoc tag goes on its own,
+   * separate line. E.g.
+   *
+   * Calculate the square of the given number
+   *
+   * @param d the Double to square
+   * @return the result of squaring d
+   */
+  def square(d: Double): Double = d * d
+
+

Tags

+

Class specific tags

+

@constructor placed in the class comment will describe the primary constructor. +Method specific tags

+

@return detail the return value from a method (one per method). +Method, Constructor and/or Class tags

+

@throws what exceptions (if any) the method or constructor may throw.

+

@param detail a value parameter for a method or constructor, provide one per parameter to the method/constructor.

+

@tparam detail a type parameter for a method, constructor or class. Provide one per type parameter.

+

Usage tags

+

@see reference other sources of information like external document links or related entities in the documentation.

+

@note add a note for pre or post conditions, or any other notable restrictions or expectations.

+

@example for providing example code or related example documentation.

+

@usecase provide a simplified method definition for when the full method definition is too complex or noisy. An example is (in the collections API), providing documentation for methods that omit the implicit canBuildFrom.

+

Member grouping tags

+

@group <group> - mark the entity as a member of the group.

+

@groupname <group> <name> - provide an optional name for the group. is displayed as the group header +before the group description.

+

@groupdesc <group> <description> - add optional descriptive text to display under the group name. Supports multiline formatted text.

+

@groupprio - control the order of the group on the page. Defaults to 0. Ungrouped elements have an implicit priority of 1000. Use a value between 0 and 999 to set a relative position to other groups. Low values will appear before high values.

+

Diagram tags

+

@contentDiagram - use with traits and classes to include a content hierarchy diagram showing included types. The diagram content can be fine tuned with additional specifiers taken from hideNodes, hideOutgoingImplicits, hideSubclasses, hideEdges, hideIncomingImplicits, hideSuperclasses and hideInheritedNode. hideDiagram can be supplied to prevent a diagram from being created if it would be created by default. Packages and objects have content diagrams by default.

+

@inheritanceDiagram

+

Other tags

+

@author provide author information for the following entity

+

@version the version of the system or API that this entity is a part of.

+

@since like @version but defines the system or API that this entity was first defined in.

+

@todo for documenting unimplemented features or unimplemented aspects of an entity.

+

@deprecated marks the entity as deprecated, providing both the replacement implementation that should be used and the version/date at which this entity was deprecated.

+

@migration like deprecated but provides advanced warning of planned changes ahead of deprecation. Same fields as @deprecated.

+

@inheritdoc take comments from a superclass as defaults if comments are not provided locally.

+

@documentable Expand a type alias and abstract type into a full template page. - TODO: Test the “abstract type” claim - no examples of this in the Scala code base

+

Macros

+

@define <name> <definition> allows use of $name in other Scaladoc comments within the same source file which will be expanded to the contents of <definition>.

+

Markup

+
 `monospace`
+ ''italic text''
+ '''bold text'''
+ __underline__
+ ^superscript^
+ ,,subscript,,
+ [[entity link]], e.g. [[scala.collection.Seq]]
+ [[https://external.link External Link]],
+   e.g. [[https://scala-lang.org Scala Language Site]]
+
+

Other formatting notes

+

Paragraphs are started with one (or more) blank lines.

+

* in the margin for the comment is valid (and should be included) but the line should be blank otherwise.

+

Code blocks are contained within {{{ this }}} and may be multi-line.

+

Indentation is relative to the starting * for the comment.

+

Headings are defined with surrounding = characters, with more = denoting subheadings. E.g. =Heading=, ==Sub-Heading==, etc.

+

List blocks are a sequence of list items with the same style and level, with no interruptions from other block styles. Unordered lists can be bulleted using -, while numbered lists can be denoted using 1., i., I., a. for the various numbering styles.

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Scala/sbt/index.html b/Scala/sbt/index.html new file mode 100644 index 0000000..dd78b51 --- /dev/null +++ b/Scala/sbt/index.html @@ -0,0 +1,3434 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sbt - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Sbt

+ + +

SBT Home Page

+

Scala school's SBT page

+

SBT: The Missing Tutorial

+

Create a New Project

+
$ sbt new sbt/scala-seed.g8
+$ cd hello
+$ sbt
+...
+> run
+> exit
+
+

Giter8 templates

+

Layout

+

sbt uses the same directory structure as Maven for source files by default (all paths are relative to the base directory):

+
src/
+  main/
+    resources/
+       <files to include in main jar here>
+    scala/
+       <main Scala sources>
+    java/
+       <main Java sources>
+  test/
+    resources
+       <files to include in test jar here>
+    scala/
+       <test Scala sources>
+    java/
+       <test Java sources>
+
+

Other directories in src/ will be ignored. Additionally, all hidden directories will be ignored.

+

Source code can be placed in the project’s base directory as hello/app.scala, which may be for small projects, though for normal projects people tend to keep the projects in the src/main/ directory to keep things neat.

+

Build Definition

+

The build definition goes in a file called build.sbt, located in the project’s base directory. The “base directory” is the directory containing the project. +In addition to build.sbt, the project directory can contain .scala files that defines helper objects and one-off plugins.

+
build.sbt
+project/
+  Dependencies.scala
+
+

.gitignore (or equivalent for other version control systems) should contain:

+
target/
+
+

As part of your build definition, specify the version of sbt that your build uses. This allows people with different versions of the sbt launcher to build the same projects with consistent results. +To do this, create a file named project/build.properties that specifies the sbt version as follows:

+
sbt.version=1.0.2
+
+

A build definition is defined in build.sbt, and it consists of a set of projects (of type Project). Because the term project can be ambiguous, we often call it a subproject.

+
lazy val root = (project in file("."))
+  .settings(
+    name := "Hello",
+    scalaVersion := "2.12.3"
+  )
+
+

Each subproject is configured by key-value pairs.

+

build.sbt may also be interspersed with vals, lazy vals, and defs. Top-level objects and classes are not allowed in build.sbt. +Those should go in the project/ directory as Scala source files.

+

There are three flavors of key:

+
SettingKey[T]: a key for a value computed once (the value is computed when loading the subproject, and kept around).
+TaskKey[T]: a key for a value, called a task, that has to be recomputed each time, potentially with side effects.
+InputKey[T]: a key for a task that has command line arguments as input. Check out Input Tasks for more details.
+
+

Built-in Keys

+

The built-in keys are just fields in an object called Keys. A build.sbt implicitly has an import sbt.Keys._, so sbt.Keys.name can be referred to as name.

+

Adding Library Dependencies

+

To depend on third-party libraries, there are two options. The first is to drop jars in lib/ (unmanaged dependencies) and the other is to add managed dependencies, which will look like this in build.sbt:

+
val derby = "org.apache.derby" % "derby" % "10.4.1.3"
+
+lazy val commonSettings = Seq(
+  organization := "com.example",
+  version := "0.1.0-SNAPSHOT",
+  scalaVersion := "2.12.3"
+)
+
+lazy val root = (project in file("."))
+  .settings(
+    commonSettings,
+    name := "Hello",
+    libraryDependencies += derby
+  )
+
+

The libraryDependencies key involves two complexities: += rather than :=, and the % method. += appends to the key’s old value rather than replacing it. +The % method is used to construct an Ivy module ID from strings.

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Search/ElasticSearch/index.html b/Search/ElasticSearch/index.html new file mode 100644 index 0000000..21695a2 --- /dev/null +++ b/Search/ElasticSearch/index.html @@ -0,0 +1,4381 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ElasticSearch Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Cheatsheets

+

Jolicode

+

Development URLs

+

Kibana (port 5601)

+

Sense

+

ElasticSearch (port 9200)

+

INSTALL

+
    +
  1. Install curl
  2. +
  3. Install Java
  4. +
  5. Download ElasticSearch
  6. +
  7. Optionally change the cluster.name in the elasticsearch.yml configuration
  8. +
+
cd elasticsearch-<version>
+./bin/elasticsearch -d
+# or on Windows
+# bin\elasticsearch.bat
+curl 'https://localhost:9200/?pretty'
+
+
    +
  1. +

    Install Kibana

    +
      +
    • Open config/kibana.yml in an editor
    • +
    • Set the elasticsearch.url to point at your Elasticsearch instance
    • +
    • Run ./bin/kibana (orbin\kibana.bat on Windows)
    • +
    • Point your browser at https://localhost:5601
    • +
    +
  2. +
  3. +

    Install Sense

    +
  4. +
+
./bin/kibana plugin --install elastic/sense
+
+

On Windows:

+
bin\kibana.bat plugin --install elastic/sense
+
+

Then go to

+

https://localhost:5601/app/sense

+

CURL

+
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
+
+

verb is GET, POST, PUT, HEAD, or DELETE

+

Examples

+
curl -XGET 'https://localhost:9200/_count?pretty' -d '{ "query": { "match_all": {} }}'
+
+
curl -XGET <id>.us-west-2.es.amazonaws.com
+
+curl -XGET 'https://<id>.us-west-2.es.amazonaws.com/_count?pretty' -d '{ "query": { "match_all": {} } }'
+
+curl -XPUT https://<id>.us-west-2.es.amazonaws.com/movies/movie/tt0116996 -d '{"directors" : ["Tim Burton"],"genres" : ["Comedy","Sci-Fi"], "plot": "The Earth is invaded by Martians with irresistible weapons and a cruel sense of humor.", "title" : "Mars Attacks!", "actors" :["Jack Nicholson","Pierce Brosnan","Sarah Jessica Parker"], "year" : 1996}'
+
+

Sense

+

Sense syntax is similar to curl:

+

Index a document

+
PUT index/type/1
+{
+ "body": "here"
+}
+
+

and retrieve it

+
GET index/type/1
+
+

PLUGINS

+

URL pattern

+

https://yournode:9200/_plugin/<plugin name>

+

On Debian, the script is in: /usr/share/elasticsearch/bin/plugin.

+

Install various plugins

+

./bin/plugin --install mobz/elasticsearch-head
+./bin/plugin --install lmenezes/elasticsearch-kopf/1.2
+./bin/plugin --install elasticsearch/marvel/latest
+
+Remove a plugin

+
./bin/plugin --remove
+
+

List installed plugins

+
./bin/plugin --list
+
+
GET /_nodes?plugin=true
+
+

Elasticsearch monitoring and management plugins

+

Head

+

Head

+
    +
  1. elasticsearch/bin/plugin -install mobz/elasticsearch-head
  2. +
  3. open https://localhost:9200/_plugin/head
  4. +
+

elastichq.org

+

BigDesk

+

Live charts and statistics for elasticsearch cluster: +BigDesk

+

Kopf

+

Kopf

+
./bin/plugin --install lmenezes/elasticsearch-kopf/1.2`
+
+

Marvel

+
./bin/plugin --install elasticsearch/marvel/latest
+
+

Integrations (CMS, import/export, hadoop...)

+

Integrations

+

Aspire

+

Aspire

+

Aspire is a framework and libraries of extensible components designed to enable creation of solutions to acquire data from one or more content repositories (such as file systems, relational databases, cloud storage, or content management systems), extract metadata and text from the documents, analyze, modify and enhance the content and metadata if needed, and then publish each document, together with its metadata, to a search engine or other target application

+

Docs

+

Integration with Hadoop

+

Integration with Hadoop

+

Bulk loading for elastic search https://infochimps.com

+

Integration with Spring

+

Spring Data

+

WordPress

+

Wordpress

+

TOOLS

+

BI platforms that can use ES as an analytics engine:

+
    +
  • Kibana
  • +
  • Grafana
  • +
  • BIRT
  • +
  • Birt
  • +
  • +

    Birt

    +
  • +
  • +

    Adminer

    +
  • +
  • Adminer.org
  • +
  • +

    Database management in a single PHP file. Works with MySQL, PostgreSQL, SQLite, MS SQL, Oracle, SimpleDB, Elasticsearch, MongoDB. Needs a webserver + PHP: WAMP

    +
  • +
  • +

    Mongolastic

    +
  • +
  • A tool that migrates data from MongoDB to Elasticsearch and vice versa
  • +
  • +

    Mongolastic

    +
  • +
  • +

    Elasticsearch-exporter

    +
  • +
  • Elasticsearch-exporter
  • +
+

Code Examples - developing a Web UI for ES

+ +

Java API

+ +

BASICS

+

An Elasticsearch cluster can contain multiple indices, which in turn contain multiple types. These types hold multiple documents, and each document has multiple fields.

+

Explore (using Sense)

+

GET _stats/

+

# List indices

+
GET /_cat/indices/
+GET /_cat/indices/my_ind*
+
+

# Get info about one index

+
GET /twitter
+GET /my_index_nr_1*/_settings?pretty   or ?v
+GET /twitter/_settings,_mappings
+
+

The available features are _settings,_mappings, _warmers and_aliases

+

# cluster

+
GET /_nodes
+
+

# insert data

+
PUT my_index/user/1
+{
+"first_name":    "John",
+"last_name":     "Smith",
+"date_of_birth": "1970-10-24"
+}
+
+

#search

+
GET my_index/_search
+
+GET _count?pretty
+
+

# Data schema

+
GET my_index/_mapping
+
+

INSERT DOCUMENTS

+
PUT /index/type/ID
+PUT /megacorp/employee/1
+{ "first_name" : "John", "last_name" : "Smith", "age" : 25, "about" : "I love to go rock climbing", "interests": [ "sports", "music" ]}
+
+PUT /megacorp/employee/2
+{ "first_name" : "Jane", "last_name" : "Smith", "age" : 32, "about" : "I like to collect rock albums", "interests": [ "music" ]}
+
+GET /megacorp/employee/1
+
+

Field names can be any valid string, but may not include periods. +Every document in Elasticsearch has a version number. Every time a change is made to a document (including deleting it), the _version number is incremented.

+

Optimistic concurrency control

+
PUT /website/blog/1?version=1  { "title": "My first blog entry", "text": "Starting to get the hang of this..."}
+
+We want this update to succeed only if the current _version of this document in our index is version 1
+
+External version:
+
+PUT /website/blog/2?version=5&version_type=external { "title": "My first external blog entry", "text": "Starting to get the hang of this..."}
+
+

INSERT DOCUMENTS - AUTOGENERATED IDS

+
POST /website/blog/
+{
+"title": "My second blog entry",
+"text":  "Still trying this out...",
+"date":  "2014/01/01"
+}
+
+

Response:

+
{
+"_index":    "website",
+"_type":     "blog",
+"_id":       "AVFgSgVHUP18jI2wRx0w",
+"_version":  1,
+"created":   true
+}
+
+

# creating an entirely new document and not overwriting an existing one

+
PUT /website/blog/123?op_type=create { ... }
+PUT /website/blog/123/_create { ... }
+
+

RETRIEVE DOCUMENTS

+
GET /website/blog/123  # optional ?pretty
+
+

{ "_index" : "website", "_type" : "blog", "_id" : "123", "_version" : 1, "found" : true, "_source" : { "title": "My first blog entry", "text": "Just trying this out...", "date": "2014/01/01" }}

+

# Contains just the fields that we requested

+
GET /website/blog/123?_source=title,text
+
+

# Just get the original doc

+
GET /website/blog/123/_source
+
+

# check if doc exists -- HTTP 200 or 404

+
curl -i -XHEAD https://localhost:9200/website/blog/123
+
+

# Note: HEAD/exists requests do not work in Sense +# because they only return HTTP headers, not +# a JSON body

+

# multiple docs at once

+
GET /website/blog/_mget { "ids" : [ "2", "1" ]}
+
+

UPDATE

+

Documents in Elasticsearch are immutable; we cannot change them. Instead, if we need to update an existing document, we reindex or replace it

+

# Accepts a partial document as the doc parameter, which just gets merged with the existing document.

+
POST /website/blog/1/_update
+{ "doc" : { "tags" : [ "testing" ], "views": 0 }}
+
+

# Script

+
POST /website/blog/1/_update
+{ "script" : "ctx._source.views+=1"}
+
+

# script with parameters

+
POST /website/blog/1/_update
+{ "script" : "ctx._source.tags+=new_tag", "params" : { "new_tag" : "search" }}
+
+

# upsert

+
POST/website/pageviews/1/_update
+{"script":"ctx._source.views+=1","upsert":{"views":1}}
+
+

DELETE

+
DELETE /website/blog/123
+
+

# delete doc based on its contents

+
POST /website/blog/1/_update { "script" : "ctx.op = ctx._source.views == count ? 'delete' : 'none'", "params" : { "count": 1 }}
+
+

BULK

+
POST /_bulk
+{"delete":{"_index":"website","_type":"blog","_id":"123"}}
+{"create":{"_index":"website","_type":"blog","_id":"123"}} #  Create a document only if the document does not already exist
+{"title":"My first blog post"}
+{"index":{"_index":"website","_type":"blog"}}
+{"title":"My second blog post"}
+{"update":{"_index":"website","_type":"blog","_id":"123","_retry_on_conflict":3}}
+{"doc":{"title":"My updated blog post"}}
+
+

Bulk in the same index or index/type

+
POST /website/_bulk
+{"index":{"_type":"log"}}
+{"event":"User logged in"}
+{"index":{"_type":"blog"}}
+{"title":"My second blog post"}
+
+

Try around 5-15MB in size.

+ +

Every field in a document is indexed and can be queried.

+

# Search for all employees in the megacorp index:

+
GET /megacorp/employee/_search
+
+

# Search for all employees in the megacorp index +# who have "Smith" in the last_name field

+
GET /megacorp/employee/_search?q=last_name:Smith
+
+

# Same query as above, but using the Query DSL

+
GET /megacorp/employee/_search
+{
+    "query": {
+      "match": {
+        "last_name": "smith"
+      }
+    }
+}
+
+

# SEARCH QUERY STRING

+
GET /_all/tweet/_search?q=tweet:elasticsearch
+
+

Don't forget to URL encode special characters e.g. +name:john +tweet:mary

+
GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary
+
+

The + prefix indicates conditions that must be satisfied for our query to match. Similarly a - prefix would indicate conditions that must not match. All conditions without a + or - are optional

+
+name:(mary john) +date:>2014-09-10 +(aggregations geo) # last part searches _all
+
+

QUERY DSL

+

When used in filtering context, the query is said to be a "non-scoring" or "filtering" query. That is, the query simply asks the question: "Does this document match?". The answer is always a simple, binary yes|no. +When used in a querying context, the query becomes a "scoring" query.

+
# Find all employees whose `last_name` is Smith
+# and who are older than 30
+GET /megacorp/employee/_search
+{
+"query" : {
+  "filtered" : {
+      "filter" : {
+      "range" : {
+          "age" : { "gt" : 30 }
+      }
+      },
+      "query" : {
+      "match" : {
+          "last_name" : "smith"
+      }
+      }
+  }
+}
+}
+
+

MATCH

+

# Find all employees who enjoy "rock" or "climbing"

+
GET /megacorp/employee/_search
+{
+"query" : {
+  "match" : {
+      "about" : "rock climbing"
+  }
+}
+}
+
+

The match query should be the standard query that you reach for whenever you want to query for a full-text or exact value in almost any field. +If you run a match query against a full-text field, it will analyze the query string by using the correct analyzer for that field before executing the search +If you use it on a field containing an exact value, such as a number, a date, a Boolean, or a not_analyzedstring field, then it will search for that exact value

+

MATCH ON MULTIPLE FIELDS

+
{
+"multi_match": {
+  "query":    "full text search",
+  "fields":  [ "title", "body" ]
+}}
+
+ +

# Find all employees who enjoy "rock climbing"

+
GET /megacorp/employee/_search
+{
+"query" : {
+  "match_phrase" : {
+      "about" : "rock climbing"
+  }
+}
+}
+
+

# EXACT VALUES

+

The term query is used to search by exact values, be they numbers, dates, Booleans, or not_analyzed exact-value string fields

+

The terms query is the same as the term query, but allows you to specify multiple values to match. If the field contains any of the specified values, the document matches

+
{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
+
+

# Compound Queries

+

{ + "bool": { + "must": { "match": { "tweet": "elasticsearch" }}, + "must_not": { "match": { "name": "mary" }}, + "should": { "match": { "tweet": "full text" }}, + "filter": { "range": { "age" : { "gt" : 30 }} } + } + }

+

# VALIDATE A QUERY

+

GET /gb/tweet/_validate/query?explain { "query": { "tweet" : { "match" : "really powerful" } }}

+

# understand why one particular document matched or, more important, why it didn’t match

+

GET /us/tweet/12/_explain { "query" : { "bool" : { "filter" : { "term" : { "user_id" : 2 }}, "must" : { "match" : { "tweet" : "honeymoon" }} } }}

+

MULTIPLE INDICES OR TYPES

+
# all documents all indices
+
+

/_search

+

/gb,us/_search + Search all types in the gb and us indices

+

/g,u/_search + Search all types in any indices beginning with g or beginning with u

+

/gb/user/_search + Search type user in the gb index

+

/gb,us/user,tweet/_search + Search types user and tweet in the gb and us indices

+

/_all/user,tweet/_search + Search types user and tweet in all indices

+

PAGINATION

+
 GET /_search?size=5GET /_search?size=5&from=5
+
+

SORTING

+
 GET /_search { "query" : { "bool" : { "filter" : { "term" : { "user_id" : 1 }} } }, "sort": { "date": { "order": "desc" }}}
+
+

For string sorting, use multi-field mapping:

+
 "tweet": { "type": "string", "analyzer": "english", "fields": { "raw": {"type": "string", "index": "not_analyzed" } }}
+
+

The main tweet field is just the same as before: an analyzed full-text field. +The new tweet.raw subfield is not_analyzed.

+

then sort on the new field

+
 GET /_search { "query": { "match": { "tweet": "elasticsearch" } }, "sort": "tweet.raw"}
+
+

HIGHLIGHTS

+

# Find all employees who enjoy "rock climbing" - highlights +# and highlight the matches

+

GET /megacorp/employee/_search + { + "query" : { + "match_phrase" : { + "about" : "rock climbing" + } + }, + "highlight": { + "fields" : { + "about" : {} + } + } + }

+

ANALYSIS

+

An analyzer is really just a wrapper that combines three functions into a single package:

+
* Character filters
+* Tokenizer
+* Token filters
+
+

# See how text is analyzed

+

GET /_analyze { "analyzer": "standard", "text": "Text to analyze"}

+

# test analyzer

+

GET /gb/_analyze { "field": "tweet", "text": "Black-cats"}

+

MAPPINGS (schemas)

+

Every type has its own mapping, or schema definition. A mapping defines the fields within a type, the datatype for each field, and how the field should be handled by Elasticsearch. A mapping is also used to configure metadata associated with the type.

+

You can control dynamic nature of mappings

+

Mapping (or schema definition) for the tweet type in the gb index

+
  GET /gb/_mapping/tweet
+
+

Elasticsearch supports the following simple field types:

+
    +
  • String: string
  • +
  • Whole number: byte, short, integer, long
  • +
  • Floating-point: float, double
  • +
  • Boolean: boolean
  • +
  • Date: date
  • +
+

Fields of type string are, by default, considered to contain full text. That is, their value will be passed through an analyzer before being indexed, and a full-text query on the field will pass the query string through an analyzer before searching. +The two most important mapping attributes for string fields are index and analyzer.

+

The index attribute controls how the string will be indexed. It can contain one of three values:

+
    +
  • analyzed First analyze the string and then index it. In other words, index this field as full text.
  • +
  • not_analyzed Index this field, so it is searchable, but index the value exactly as specified. Do not analyze it.
  • +
  • no Don’t index this field at all. This field will not be searchable.
  • +
+

If we want to map the field as an exact value, we need to set it to not_analyzed:

+
  {
+    "tag": {
+    "type": "string",
+    "index": "not_analyzed"
+    }
+  }
+
+

For analyzed string fields, use the analyzer attribute to specify which analyzer to apply both at search time and at index time. By default, Elasticsearch uses the standard analyzer, but you can change this by specifying one of the built-in analyzers, such as whitespace, simple, or english:

+
  {
+    "tweet": {
+    "type": "string",
+    "analyzer": "english"
+    }
+  }
+
+

# create a new index, specifying that the tweet field should use the english analyzer

+

PUT /gb + { "mappings": + { "tweet" : + { "properties" : { + "tweet" : { "type" : "string", "analyzer": "english" }, + "date" : { "type" : "date" }, + "name" : { "type" : "string" }, + "user_id" : { "type" : "long" } + }}}}

+

null, arrays, objects: see complex core fields

+

Parent Child Relationships

+
DELETE /test_index
+
+PUT /test_index
+{
+   "mappings": {
+      "parent_type": {
+         "properties": {
+            "num_prop": {
+               "type": "integer"
+            },
+            "str_prop": {
+               "type": "string"
+            }
+         }
+      },
+      "child_type": {
+         "_parent": {
+            "type": "parent_type"
+         },
+         "properties": {
+            "child_num": {
+               "type": "integer"
+            },
+            "child_str": {
+               "type": "string"
+            }
+         }
+      }
+   }
+}
+
+POST /test_index/_bulk
+{"index":{"_type":"parent_type","_id":1}}
+{"num_prop":1,"str_prop":"hello"}
+{"index":{"_type":"child_type","_id":1,"_parent":1}}
+{"child_num":11,"child_str":"foo"}
+{"index":{"_type":"child_type","_id":2,"_parent":1}}
+{"child_num":12,"child_str":"bar"}
+{"index":{"_type":"parent_type","_id":2}}
+{"num_prop":2,"str_prop":"goodbye"}
+{"index":{"_type":"child_type","_id":3,"_parent":2}}
+{"child_num":21,"child_str":"baz"}
+
+POST /test_index/child_type/_search
+
+POST /test_index/child_type/2?parent=1
+{
+   "child_num": 13,
+   "child_str": "bars"
+}
+
+POST /test_index/child_type/_search
+
+POST /test_index/child_type/3/_update?parent=2
+{
+   "script": "ctx._source.child_num+=1"
+}
+
+POST /test_index/child_type/_search
+
+POST /test_index/child_type/_search
+{
+    "query": {
+        "term": {
+           "child_str": {
+              "value": "foo"
+           }
+        }
+    }
+}
+
+POST /test_index/parent_type/_search
+{
+   "query": {
+      "filtered": {
+         "query": {
+            "match_all": {}
+         },
+         "filter": {
+            "has_child": {
+               "type": "child_type",
+               "filter": {
+                  "term": {
+                     "child_str": "foo"
+                  }
+               }
+            }
+         }
+      }
+   }
+}
+
+

AGGREGATES

+

Aggregations and searches can span multiple indices

+

# Calculate the most popular interests for all employees

+

GET /megacorp/employee/_search + { + "aggs": { + "all_interests": { + "terms": { + "field": "interests" + } + } + } + }

+

# Calculate the most popular interests for +# employees named "Smith"

+

GET /megacorp/employee/_search + { + "query": { + "match": { + "last_name": "smith" + } + }, + "aggs": { + "all_interests": { + "terms": { + "field": "interests" + } + } + } + }

+

# Calculate the average age of employee per interest - hierarchical aggregates

+

GET /megacorp/employee/_search + { + "aggs" : { + "all_interests" : { + "terms" : { "field" : "interests" }, + "aggs" : { + "avg_age" : { + "avg" : { "field" : "age" } + } + } + } + } + }

+

# requires in config/elasticsearch.yml +# script.inline: true +# script.indexed: true

+

GET /tlo/contacts/_search + { + "size" : 0, + "query": { + "constant_score": { + "filter": { + "terms": { + "version": [ + "20160301", + "20160401" + ] + } + } + } + }, + "aggs": { + "counts": { + "cardinality": { + "script": "doc['first_name'].value + ' ' + doc['last_name'].value + ' ' + doc['company'].value", + "missing": "N/A" + } + } + } + }

+

INDEX MANAGEMENT

+

By default, indices are assigned five primary shards. The number of primary shards can be set only when an index is created and never changed

+

# Add an index

+
  PUT /blogs { "settings" : { "number_of_shards" : 3, "number_of_replicas" : 1 }}
+  PUT /blogs/_settings { "number_of_replicas" : 2}
+
+
    +
  • ElasticSearch Shards should be 50 GB or less in size.
  • +
  • Use aliases to shelter the underlying index (or indices) and allow index swapping
  • +
+

CLUSTER MANAGEMENT

+
 GET /_cluster/health
+
+

CONFIGURATION

+
    +
  • config directory
  • +
  • +

    yaml file

    +
  • +
  • +

    Sets the JVM heap size to 0.5 memory size. The OS will use it for file system cache

    +
  • +
  • Prefer not to allocate 30GB !! --> uncompressed pointers
  • +
  • Never let the JVM swap bootstrap.mlockall = true
  • +
  • Keep the JVM defaults
  • +
  • Do not use G1GC alternative garbage collector
  • +
+
cluster.name: <my cluster>
+
+
    +
  • All nodes in the cluster must have the same cluster name
  • +
+
node.name: <my_node_name>
+
+
./bin/elasticsearch --node.name=`hostname`
+
+

to override the configuration file

+
    +
  • HTTP port: 9200 and successors
  • +
  • Transport : 9300 (internal communications)
  • +
+

Discovery

+
    +
  • AWS plugin available --> also include integration with S3 (snapshot to S3)
  • +
  • AWS: multi-AZ is OK but replication across far data centers is not recommended
  • +
  • See: resiliency
  • +
+

Sites plugins -- kopf / head / paramedic / bigdesk / kibana +* contain static web content (JS, HTML....)

+

Install plugins on ALL machines of the cluster

+

To install,

+
  ./bin/plugin install marvel-agent
+  ./bin/plugin remove marvel-agent
+
+

One type per index is recommended, except for parent child / nested indexes.

+

index size optimization:

+
    +
  • can disable _source and _all (the index that captures every field - not needed unless the top search bar changes)
  • +
  • by default, Kibana will search _all
  • +
+

data types: +string, number, bool, datetime, binary, array, object, geo_point, geo_shape, ip, multifield +binary should be base64 encoded before storage

+

MAINTENANCE

+

Steps to restore elastic search data:

+
    +
  1. Stop elastic search
  2. +
  3. Extract the zip file (dump file)
  4. +
  5. Start elastic search
  6. +
  7. Reload elastic search
  8. +
+

The commands to do the above are as below:

+
    +
  1. systemctl stop elasticsearch
  2. +
  3. extract gz file to destination path
  4. +
  5. systemctl start elasticsearch
  6. +
  7. systemctl daemon-reload elasticsearch
  8. +
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Search/Logstash/index.html b/Search/Logstash/index.html new file mode 100644 index 0000000..8b05992 --- /dev/null +++ b/Search/Logstash/index.html @@ -0,0 +1,3439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LogStash - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

LogStash

+

Operations

+

logstash -w 4 to set the number of worker threads

+

Use path.data to distribute the data on multiple (EBS) disks

+

Outputs

+
    +
  • MongoDB
  • +
  • PagerDuty
  • +
  • Nagios
  • +
  • Graphite
  • +
  • Ganglia
  • +
  • StatsD
  • +
  • Redis
  • +
  • RabbitMQ
  • +
+
output {
+     elasticsearch { }   # https://localhost:9200
+}
+
+
output {
+     redis {
+          host => "redis.example.com"
+          data_type =>: "list"
+
+     }
+}
+
+

Output to file

+
output {
+      file {
+
+     }
+}
+
+

Filtering

+

Use "date" for normalizing dates:

+
filter {
+     date{
+         timezone => "America/Los_Angeles"
+         locale => "en"      # English
+
+     }
+     geoip {
+
+         source => "clientip"   # will read from clientip field
+          database =>  ... # use MaxMind's GeoLiteCity by default
+     }
+     useragent {
+
+     }
+}
+
+

Mutate a field

+
filter {
+     if [action] == "login {
+          mutate { remove_field => "secret" }
+     }
+}
+
+

Conditionals both in filter and outputs

+
regexp
+=~
+!~
+
+
output {
+     if [loglevel] == "ERROR"
+
+}
+
+

Interesting Plugins

+

Stanford NLP library logstash plugin

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Software_Development/Development_Tools/index.html b/Software_Development/Development_Tools/index.html new file mode 100644 index 0000000..39ab81c --- /dev/null +++ b/Software_Development/Development_Tools/index.html @@ -0,0 +1,3558 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Development Tools - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Development Tools

+ +

Communication / IM

+
    +
  • Slack
  • +
  • Trillian / Pandion
  • +
  • Skype, WeChat, Viber, Hangouts
  • +
+

Wiki / Knowledge Base

+
    +
  • Confluence
  • +
  • Evernote
  • +
+

Project / Bug Tracking

+
    +
  • JIRA
  • +
  • Bugzilla
  • +
  • Mantis
  • +
  • RedMine
  • +
  • TFS
  • +
+

Enterprise Architecture / UML

+
    +
  • Violet UML Editor
  • +
  • Visio
  • +
  • Rational Rose
  • +
+

Terminals / SSH

+
    +
  • Putty
  • +
  • MobaXterm
  • +
  • mRemoteNG
  • +
  • Remote Desktop Connection Manager
  • +
+

Editors/ IDEs

+ +

for Python

+
    +
  • Python Tools for Visual Studio
  • +
  • PyDev
  • +
  • PyCharm
  • +
  • Anaconda
  • +
+

Source Control

+
    +
  • SourceTree (Atlassian)
  • +
  • GitHub
  • +
  • TortoiseGit
  • +
+

Code Quality

+ +

Virtual Machines and Containers

+ +

SQL Tools

+
    +
  • MySQL Workbench
  • +
  • HeidiSQL
  • +
  • Aginity Workbench for Redshift (AWS)
  • +
+

MongoDB tools

+
    +
  • RoboMongo
  • +
  • MongoChef
  • +
  • MongoDB Compass
  • +
+

Data Quality

+
    +
  • DQ Analyzer (Attacama)
  • +
+

Data Science

+
    +
  • Jupyter / IPython
  • +
  • Rodeo
  • +
  • Gephi
  • +
+

AWS

+
    +
  • S3 Browser
  • +
  • FastGlacier
  • +
+

File Handling

+
    +
  • 7zip
  • +
  • FileZilla
  • +
  • FolderSize
  • +
+

Other

+ + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Software_Development/Eclipse/index.html b/Software_Development/Eclipse/index.html new file mode 100644 index 0000000..b5ac6d2 --- /dev/null +++ b/Software_Development/Eclipse/index.html @@ -0,0 +1,3314 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Useful Links - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Software_Development/IntelliJ/index.html b/Software_Development/IntelliJ/index.html new file mode 100644 index 0000000..cca7420 --- /dev/null +++ b/Software_Development/IntelliJ/index.html @@ -0,0 +1,3316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IntelliJ Cheatsheet - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

IntelliJ

+

Shortcuts

+
Search Anywhere     Double Shift
+Got to file         Ctrl + Shift + N
+Recent files        Ctrl + E
+Code Completion     Ctrl + Space 
+Parameters          Ctrl + P
+Highlight usages in file            Ctrl + Shift + F7
+Declaration of the current method   Alt + Q
+Code Templates      Ctrl + J
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Web/Bootstrap/index.html b/Web/Bootstrap/index.html new file mode 100644 index 0000000..066200a --- /dev/null +++ b/Web/Bootstrap/index.html @@ -0,0 +1,3349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bootstrap - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Bootstrap

+ +

Bootstrap

+ +

Bootstrap

+

Install

+
npm install bootstrap
+
+

CDN

+
<!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
+
+<!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
+
+<!-- Latest compiled and minified JavaScript --><script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
+
+ + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Web/CORS/index.html b/Web/CORS/index.html new file mode 100644 index 0000000..5fe14a8 --- /dev/null +++ b/Web/CORS/index.html @@ -0,0 +1,3355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CORS - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

CORS

+ +

Certain "cross-domain" requests, notably AJAX requests, are forbidden by default by the same-origin security policy of web browsers.

+

The same-origin policy is an important security concept implemented by web browsers to prevent Javascript code from making requests against a different origin (e.g., different domain, more precisely combination of URI scheme, hostname, and port number ) than the one from which it was served. Although the same-origin policy is effective in preventing resources from different origins, it also prevents legitimate interactions between a server and clients of a known and trusted origin.

+

Cross-Origin Resource Sharing (CORS) is a technique for relaxing the same-origin policy, allowing Javascript on a web page to consume a REST API served from a different origin.

+

Cross-origin requests come in two flavors:

+
    +
  1. simple requests
  2. +
  3. "not-so-simple requests" (a term just made up)
  4. +
+

Simple Requests

+

Simple requests are requests that meet the following criteria:

+

HTTP Method matches (case-sensitive) one of:

+
    +
  • HEAD
  • +
  • GET
  • +
  • POST
  • +
+

HTTP Headers matches (case-insensitive):

+
    +
  • Accept
  • +
  • Accept-Language
  • +
  • Content-Language
  • +
  • Last-Event-ID
  • +
  • Content-Type, but only if the value is one of application/x-www-form-urlencoded, multipart/form-data, text/plain
  • +
+

Handling a not-so-simple request

+

A not-so-simple request looks like a single request to the client, but it actually consists of two requests under the hood. The browser first issues a preflight request, which is like asking the server for permission to make the actual request. Once permissions have been granted, the browser makes the actual request. The browser handles the details of these two requests transparently. The preflight response can also be cached so that it is not issued on every request.

+

Some Javascript libraries, such as AngularJS and Sencha Touch, send preflight requests for any kind of request. This approach is arguably safer, because it doesn't assume that a service adheres to HTTP method semantics (i.e., a GET endpoint could have been written to have side effects.)

+

API Gateway and CORS

+

How to CORS (AWS)

+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Web/jQuery/index.html b/Web/jQuery/index.html new file mode 100644 index 0000000..53a851a --- /dev/null +++ b/Web/jQuery/index.html @@ -0,0 +1,3952 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jQuery - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

jQuery

+ + +

The jQuery library exposes its methods and properties via two properties of the window object called jQuery and $. $ is simply an alias for jQuery and it's often employed because it's shorter and faster to write.

+

Embed JQuery

+

Either directly

+
<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Demo</title>
+</head>
+<body>
+<a href="https://jquery.com/">jQuery</a>
+<script src="jquery.js"></script>
+<script>
+// Your code goes here.
+</script>
+</body>
+
+

or via a CDN

+
<head>
+<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
+</head>
+
+

Launching Code on Document Ready

+
$( document ).ready(function() {
+// Your code here.
+});
+
+// Shorthand for $( document ).ready()
+$(function() {
+console.log( "ready!" );
+});
+
+

Selecting elements

+
$( "#myId" ); // Note IDs must be unique per page.
+$( ".myClass" );
+$( "input[name='first_name']" );
+$( "#contents ul.people li" );
+$( "div.myClass, ul.people" );
+
+

If you have a variable containing a DOM element, and want to select elements related to that DOM element, simply wrap it in a jQuery object.

+
var myDomElement = document.getElementById( "foo" ); // A plain DOM element.
+$( myDomElement ).find( "a" ); // Finds all anchors inside the DOM element.
+
+

Pull a native DOM element from a jQuery object

+

A jQuery object is an array-like wrapper around one or more DOM elements.

+
$( "#foo" )[ 0 ]; // Equivalent to document.getElementById( "foo" )
+$( "#foo" ).get( 0 );
+
+

// Testing whether a selection contains elements.

+
if ( $( "div.foo" ).length ) {
+...
+}
+
+

Refining selections

+
$( "div.foo" ).has( "p" ); // div.foo elements that contain <p> tags
+$( "h1" ).not( ".bar" ); // h1 elements that don't have a class of bar
+$( "ul li" ).filter( ".current" ); // unordered list items with class of current
+$( "ul li" ).first(); // just the first unordered list item
+$( "ul li" ).eq( 5 ); // the sixth
+
+$( "form :checked" ); //  :checked targets checked checkboxes
+
+

DOM Traversal and Manipulation

+

Get the <button> element with the class 'continue' and change its HTML to 'Next Step...'

+
$( "button.continue" ).html( "Next Step..." )
+$( "h1" ).html(); // returns the html
+
+

Chaining

+
$( "#content" ).find( "h3" ).eq( 2 ).html( "new text for the third h3!" );
+$( "#content" )
+.find( "h3" )
+.eq( 2 )
+.html( "new text for the third h3!" )
+.end() // Restores the selection to all h3s in #content
+.eq( 0 )
+.html( "new text for the first h3!" );
+
+

Manipulation

+
    +
  • .html() – Get or set the HTML contents.
  • +
  • .text() – Get or set the text contents; HTML will be stripped.
  • +
  • .attr() – Get or set the value of the provided attribute.
  • +
  • .width() – Get or set the width in pixels of the first element in the selection as an integer.
  • +
  • .height() – Get or set the height in pixels of the first element in the selection as an integer.
  • +
  • .position() – Get an object with position information for the first element in the selection, relative to its first positioned ancestor. This is a getter only.
  • +
  • .val() – Get or set the value of form elements.
  • +
+

Many jQuery methods implicitly iterate over the entire collection, applying their behavior to each matched element. In most cases, the "getter" signature returns the result from the first element in a jQuery collection while the setter acts over the entire collection of matched elements.

+
$( "li" ).addClass( "newClass" ); // Each <li> in the document will have the class "newClass" added.
+
+

Add / remove class

+
$( "a" ).addClass( "test" );
+$( "a" ).removeClass( "test" );
+
+$( "div" ).click(function() {
+if ( $( this ).hasClass( "protected" ) ) {
+$( this )
+.animate({ left: -10 })
+.animate({ left: 10 })
+.animate({ left: -10 })
+.animate({ left: 10 })
+.animate({ left: 0 });
+}
+});
+
+if ( $( "#myDiv" ).is( ".pretty.awesome" ) ) {
+$( "#myDiv" ).show();
+}
+var isVisible = $( "#myDiv" ).is( ":visible" );
+if ( $( "#myDiv" ).is( ":hidden" ) ) {
+$( "#myDiv" ).show();
+}
+
+

Set / get element attributes

+
$( "a" ).attr( "href", "allMyHrefsAreTheSameNow.html" );
+$( "a" ).attr({
+title: "all titles are the same too!",
+href: "somethingNew.html"
+});
+
+

CSS

+

Getting CSS properties.

+
$( "h1" ).css( "fontSize" ); // Returns a string such as "19px".$( "h1" ).css( "font-size" ); // Also works.
+
+

Setting CSS properties.

+
$( "h1" ).css( "fontSize", "100px" ); // Setting an individual property.// Setting multiple properties.$( "h1" ).css({fontSize: "100px",color: "red"});
+
+

Data

+

Storing and retrieving data related to an element.

+
$( "#myDiv" ).data( "keyName", { foo: "bar" } );
+$( "#myDiv" ).data( "keyName" ); // Returns { foo: "bar" }
+
+

Storing a relationship between elements using .data()

+
$( "#myList li" ).each(function() {
+var li = $( this );
+var div = li.find( "div.content" );
+li.data( "contentDiv", div );
+});
+
+

Later, we don't have to find the div again; we can just read it from the list item's data

+
var firstLi = $( "#myList li:first" );
+firstLi.data( "contentDiv" ).html( "new content" );
+
+

Utility functions

+

.trim, .each, .map, inArray, isArray, isFunction, isNumeric, .type

+

Returns "lots of extra whitespace"

+
$.trim( " lots of extra whitespace " );
+
+

Iterate over an JS array or object

+
$.each([ "foo", "bar", "baz" ], function( idx, val ) {
+console.log( "element " + idx + " is " + val );
+});
+$.each({ foo: "bar", baz: "bim" }, function( k, v ) {
+console.log( k + " : " + v );
+});
+
+

HOWEVER, use this form for jQuery objects

+
$( "li" ).each( function( index, element ){
+console.log( $( this ).text() );
+});
+
+var myArray = [ 1, 2, 3, 5 ];
+if ( $.inArray( 4, myArray ) !== -1 ) {
+console.log( "found it!" );
+}
+
+
$.isArray([]); // true
+$.isFunction(function() {}); // true
+$.isNumeric(3.14); // true
+
+$.type( true ); // "boolean"
+$.type( 3 ); // "number"
+$.type( "test" ); // "string"
+$.type( function() {} ); // "function"
+$.type( new Boolean() ); // "boolean"
+$.type( new Number(3) ); // "number"
+$.type( new String('test') ); // "string"
+$.type( new Function() ); // "function"
+$.type( [] ); // "array"
+$.type( null ); // "null"
+$.type( /test/ ); // "regexp"
+$.type( new Date() ); // "date"
+
+

$.map and .map

+
<li id="a"></li>
+<li id="b"></li>
+<li id="c"></li>
+<script>
+var arr = [{
+id: "a",
+tagName: "li"
+}, {
+id: "b",
+tagName: "li"
+}, {
+id: "c",
+tagName: "li"
+}];
+
+// Returns [ "a", "b", "c" ]
+$( "li" ).map( function( index, element ) {
+return element.id;
+}).get();
+
+// Also returns [ "a", "b", "c" ]
+// Note that the value comes first with $.map
+$.map( arr, function( value, index ) {
+return value.id;
+});
+
+

Event Handling

+
var hiddenBox = $( "#banner-message" );
+$( "#button-container button" ).on( "click", function( event ) {
+hiddenBox.show();
+});
+
+

The on method is useful for binding the same handler function to multiple events, when you want to provide data to the event handler, when you are working with custom events, or when you want to pass an object of multiple events and handlers.

+

Event setup using a convenience method like .click(), .focus(), .blur(), .change()

+
$( "p" ).click(function() {
+console.log( "You clicked a paragraph!" );
+});
+
+

The hover helper function

+
$( "#menu li" ).hover(function() {
+$( this ).toggleClass( "hover" );
+});
+
+

The event object is most commonly used to prevent the default action of the event via the .preventDefault() method. However, the event object contains a number of other useful properties and methods, including:

+
pageX, pageY, type, which, data
+
+

Use this code to inspect it in your browser console

+
$( "div" ).on( "click", function( event ) {
+console.log( "event object:" );
+console.dir( event );
+});
+
+ +
$( "a" ).click(function( eventObject ) {
+var elem = $( this );
+if ( elem.attr( "href" ).match( /evil/ ) ) {
+eventObject.preventDefault();
+elem.addClass( "evil" );
+}
+});
+
+

Event setup using the .on() method with data

+
$( "input" ).on(
+"change",
+{ foo: "bar" }, // Associate data with event binding
+function( eventObject ) {
+console.log("An input value has changed! ", eventObject.data.foo);
+}
+);
+
+

// Binding multiple events with different handlers

+
$( "p" ).on({
+"click": function() { console.log( "clicked!" ); },
+"mouseover": function() { console.log( "hovered!" ); }
+});
+
+

// Tearing down all click handlers on a selection

+
$( "p" ).off( "click" );
+
+

// As of jQuery 1.7, attach an event handler to the body element that +// is listening for clicks, and will respond whenever any button is +// clicked on the page.

+
$( "body" ).on({
+click: function( event ) {
+alert( "Hello." );
+}
+}, "button" );
+
+

// An alternative to the previous example, using slightly different syntax.

+
$( "body" ).on( "click", "button", function( event ) {
+alert( "Hello." );
+});
+
+

// Attach a delegated event handler with a more refined selector

+
$( "#list" ).on( "click", "a[href^='http']", function( event ) {
+$( this ).attr( "target", "_blank" );
+});
+
+

Effects

+

Instantaneously hide all paragraphs

+
$( "p" ).hide();
+
+// slowly
+$( "p" ).hide( "slow" );
+
+

Instantaneously show all divs that have the hidden style class

+
$( "div.hidden" ).show();
+
+

Instantaneously toggle the display of all paragraphs

+
$( "p" ).toggle();
+
+

Fade in all hidden paragraphs; then add a style class to them (correct with animation callback)

+
$( "p.hidden" ).fadeIn( 750, function() {
+// this = DOM element which has just finished being animated
+$( this ).addClass( "lookAtMe" );
+});
+
+

Ajax

+
$.ajax({
+url: "/api/getWeather",
+data: {
+zipcode: 97201
+},
+success: function( result ) {
+$( "#weather-temp" ).html( "<strong>" + result + "</strong> degrees" );
+}
+});
+
+

Using the core $.ajax() method

+
$.ajax({
+// The URL for the request
+url: "post.php",
+// The data to send (will be converted to a query string)
+data: {
+id: 123
+},
+// Whether this is a POST or GET request
+type: "GET",
+// The type of data we expect back
+dataType : "json",
+})
+// Code to run if the request succeeds (is done);
+// The response is passed to the function
+.done(function( json ) {
+$( "<h1>" ).text( json.title ).appendTo( "body" );
+$( "<div class=\"content\">").html( json.html ).appendTo( "body" );
+})
+// Code to run if the request fails; the raw request and
+// status codes are passed to the function
+.fail(function( xhr, status, errorThrown ) {
+alert( "Sorry, there was a problem!" );
+console.log( "Error: " + errorThrown );
+console.log( "Status: " + status );
+console.dir( xhr );
+})
+
+

Code to run regardless of success or failure;

+
.always(function( xhr, status ) {
+alert( "The request is complete!" );
+});
+
+

Simple convenience methods such as $.get(), $.getScript(), $.getJSON(), $.post(), and $().load().

+
$.get( "myhtmlpage.html", myCallBack );  // myCallback needs to be a parameterless function
+# with parameters
+$.get( "myhtmlpage.html", function() {
+myCallBack( param1, param2 );
+});
+
+

Load

+
$(selector).load(URL,data,callback);
+
+

Using .load() to populate an element

+
$( "#newContent" ).load( "/foo.html" );
+
+

Using .load() to populate an element based on a selector

+
$( "#newContent" ).load( "/foo.html #myDiv h1:first", function( html ) {
+alert( "Content updated!" );
+});
+
+

Forms

+

Turning form data into a query string

+
$( "#myForm" ).serialize();
+
+

// Creates a query string like this: +// field_1=something&field2=somethingElse

+

Create an array of objects containing form data

+
$( "#myForm" ).serializeArray();
+
+

Use validation to check for the presence of an input

+
$( "#form" ).submit(function( event ) {
+// If .required's value's length is zero
+if ( $( ".required" ).val().length === 0 ) {
+// Usually show some kind of error message here
+// Prevent the form from submitting
+event.preventDefault();
+} else {
+// Run $.ajax() here
+}
+});
+
+

Validate a phone number field

+
$( "#form" ).submit(function( event ) {
+var inputtedPhoneNumber = $( "#phone" ).val();
+// Match only numbers
+var phoneNumberRegex = /^\d*$/;
+// If the phone number doesn't match the regex
+if ( !phoneNumberRegex.test( inputtedPhoneNumber ) ) {
+// Usually show some kind of error message here
+// Prevent the form from submitting
+event.preventDefault();
+} else {
+// Run $.ajax() here
+}
+});
+
+

Feature testing

+

Helper libraries (like Modernizr) that provide a simple, high-level API for determining if a browser has a specific feature available or not.

+
if ( Modernizr.canvas ) {
+showGraphWithCanvas();
+} else {
+showTable();
+}
+
+ + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/Windows/Command_Prompt_Here/index.html b/Windows/Command_Prompt_Here/index.html new file mode 100644 index 0000000..47f206c --- /dev/null +++ b/Windows/Command_Prompt_Here/index.html @@ -0,0 +1,3269 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Command Line - John's Cheatsheets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + + +
+
+ + + + + + + +

Command Line

+ +

Just type "cmd" to the location bar. It will start a new command prompt in current path.

+

OR

+

Hold the "Shift" key while right-clicking a blank space in the desired folder to bring up a more verbose context menu. One of the options is "Open PowerShell Here".

+

To re-enable the "Open Command Prompt Here" (disabled by the Windows 10 Creators Update):

+ + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000..1cf13b9 Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/javascripts/bundle.c8d2eff1.min.js b/assets/javascripts/bundle.c8d2eff1.min.js new file mode 100644 index 0000000..4b1b31f --- /dev/null +++ b/assets/javascripts/bundle.c8d2eff1.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var _i=Object.create;var br=Object.defineProperty;var Ai=Object.getOwnPropertyDescriptor;var Ci=Object.getOwnPropertyNames,Ft=Object.getOwnPropertySymbols,ki=Object.getPrototypeOf,vr=Object.prototype.hasOwnProperty,eo=Object.prototype.propertyIsEnumerable;var Zr=(e,t,r)=>t in e?br(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,F=(e,t)=>{for(var r in t||(t={}))vr.call(t,r)&&Zr(e,r,t[r]);if(Ft)for(var r of Ft(t))eo.call(t,r)&&Zr(e,r,t[r]);return e};var to=(e,t)=>{var r={};for(var o in e)vr.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o]);if(e!=null&&Ft)for(var o of Ft(e))t.indexOf(o)<0&&eo.call(e,o)&&(r[o]=e[o]);return r};var gr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Hi=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ci(t))!vr.call(e,n)&&n!==r&&br(e,n,{get:()=>t[n],enumerable:!(o=Ai(t,n))||o.enumerable});return e};var jt=(e,t,r)=>(r=e!=null?_i(ki(e)):{},Hi(t||!e||!e.__esModule?br(r,"default",{value:e,enumerable:!0}):r,e));var ro=(e,t,r)=>new Promise((o,n)=>{var i=c=>{try{a(r.next(c))}catch(p){n(p)}},s=c=>{try{a(r.throw(c))}catch(p){n(p)}},a=c=>c.done?o(c.value):Promise.resolve(c.value).then(i,s);a((r=r.apply(e,t)).next())});var no=gr((xr,oo)=>{(function(e,t){typeof xr=="object"&&typeof oo!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(xr,function(){"use strict";function e(r){var o=!0,n=!1,i=null,s={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function a(C){return!!(C&&C!==document&&C.nodeName!=="HTML"&&C.nodeName!=="BODY"&&"classList"in C&&"contains"in C.classList)}function c(C){var ct=C.type,Ne=C.tagName;return!!(Ne==="INPUT"&&s[ct]&&!C.readOnly||Ne==="TEXTAREA"&&!C.readOnly||C.isContentEditable)}function p(C){C.classList.contains("focus-visible")||(C.classList.add("focus-visible"),C.setAttribute("data-focus-visible-added",""))}function l(C){C.hasAttribute("data-focus-visible-added")&&(C.classList.remove("focus-visible"),C.removeAttribute("data-focus-visible-added"))}function f(C){C.metaKey||C.altKey||C.ctrlKey||(a(r.activeElement)&&p(r.activeElement),o=!0)}function u(C){o=!1}function h(C){a(C.target)&&(o||c(C.target))&&p(C.target)}function w(C){a(C.target)&&(C.target.classList.contains("focus-visible")||C.target.hasAttribute("data-focus-visible-added"))&&(n=!0,window.clearTimeout(i),i=window.setTimeout(function(){n=!1},100),l(C.target))}function A(C){document.visibilityState==="hidden"&&(n&&(o=!0),Z())}function Z(){document.addEventListener("mousemove",J),document.addEventListener("mousedown",J),document.addEventListener("mouseup",J),document.addEventListener("pointermove",J),document.addEventListener("pointerdown",J),document.addEventListener("pointerup",J),document.addEventListener("touchmove",J),document.addEventListener("touchstart",J),document.addEventListener("touchend",J)}function te(){document.removeEventListener("mousemove",J),document.removeEventListener("mousedown",J),document.removeEventListener("mouseup",J),document.removeEventListener("pointermove",J),document.removeEventListener("pointerdown",J),document.removeEventListener("pointerup",J),document.removeEventListener("touchmove",J),document.removeEventListener("touchstart",J),document.removeEventListener("touchend",J)}function J(C){C.target.nodeName&&C.target.nodeName.toLowerCase()==="html"||(o=!1,te())}document.addEventListener("keydown",f,!0),document.addEventListener("mousedown",u,!0),document.addEventListener("pointerdown",u,!0),document.addEventListener("touchstart",u,!0),document.addEventListener("visibilitychange",A,!0),Z(),r.addEventListener("focus",h,!0),r.addEventListener("blur",w,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var zr=gr((kt,Vr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof kt=="object"&&typeof Vr=="object"?Vr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof kt=="object"?kt.ClipboardJS=r():t.ClipboardJS=r()})(kt,function(){return function(){var e={686:function(o,n,i){"use strict";i.d(n,{default:function(){return Li}});var s=i(279),a=i.n(s),c=i(370),p=i.n(c),l=i(817),f=i.n(l);function u(D){try{return document.execCommand(D)}catch(M){return!1}}var h=function(M){var O=f()(M);return u("cut"),O},w=h;function A(D){var M=document.documentElement.getAttribute("dir")==="rtl",O=document.createElement("textarea");O.style.fontSize="12pt",O.style.border="0",O.style.padding="0",O.style.margin="0",O.style.position="absolute",O.style[M?"right":"left"]="-9999px";var I=window.pageYOffset||document.documentElement.scrollTop;return O.style.top="".concat(I,"px"),O.setAttribute("readonly",""),O.value=D,O}var Z=function(M,O){var I=A(M);O.container.appendChild(I);var W=f()(I);return u("copy"),I.remove(),W},te=function(M){var O=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},I="";return typeof M=="string"?I=Z(M,O):M instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(M==null?void 0:M.type)?I=Z(M.value,O):(I=f()(M),u("copy")),I},J=te;function C(D){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?C=function(O){return typeof O}:C=function(O){return O&&typeof Symbol=="function"&&O.constructor===Symbol&&O!==Symbol.prototype?"symbol":typeof O},C(D)}var ct=function(){var M=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},O=M.action,I=O===void 0?"copy":O,W=M.container,K=M.target,Ce=M.text;if(I!=="copy"&&I!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(K!==void 0)if(K&&C(K)==="object"&&K.nodeType===1){if(I==="copy"&&K.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(I==="cut"&&(K.hasAttribute("readonly")||K.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Ce)return J(Ce,{container:W});if(K)return I==="cut"?w(K):J(K,{container:W})},Ne=ct;function Pe(D){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Pe=function(O){return typeof O}:Pe=function(O){return O&&typeof Symbol=="function"&&O.constructor===Symbol&&O!==Symbol.prototype?"symbol":typeof O},Pe(D)}function xi(D,M){if(!(D instanceof M))throw new TypeError("Cannot call a class as a function")}function Xr(D,M){for(var O=0;O0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof W.action=="function"?W.action:this.defaultAction,this.target=typeof W.target=="function"?W.target:this.defaultTarget,this.text=typeof W.text=="function"?W.text:this.defaultText,this.container=Pe(W.container)==="object"?W.container:document.body}},{key:"listenClick",value:function(W){var K=this;this.listener=p()(W,"click",function(Ce){return K.onClick(Ce)})}},{key:"onClick",value:function(W){var K=W.delegateTarget||W.currentTarget,Ce=this.action(K)||"copy",It=Ne({action:Ce,container:this.container,target:this.target(K),text:this.text(K)});this.emit(It?"success":"error",{action:Ce,text:It,trigger:K,clearSelection:function(){K&&K.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(W){return hr("action",W)}},{key:"defaultTarget",value:function(W){var K=hr("target",W);if(K)return document.querySelector(K)}},{key:"defaultText",value:function(W){return hr("text",W)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(W){var K=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return J(W,K)}},{key:"cut",value:function(W){return w(W)}},{key:"isSupported",value:function(){var W=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],K=typeof W=="string"?[W]:W,Ce=!!document.queryCommandSupported;return K.forEach(function(It){Ce=Ce&&!!document.queryCommandSupported(It)}),Ce}}]),O}(a()),Li=Mi},828:function(o){var n=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function s(a,c){for(;a&&a.nodeType!==n;){if(typeof a.matches=="function"&&a.matches(c))return a;a=a.parentNode}}o.exports=s},438:function(o,n,i){var s=i(828);function a(l,f,u,h,w){var A=p.apply(this,arguments);return l.addEventListener(u,A,w),{destroy:function(){l.removeEventListener(u,A,w)}}}function c(l,f,u,h,w){return typeof l.addEventListener=="function"?a.apply(null,arguments):typeof u=="function"?a.bind(null,document).apply(null,arguments):(typeof l=="string"&&(l=document.querySelectorAll(l)),Array.prototype.map.call(l,function(A){return a(A,f,u,h,w)}))}function p(l,f,u,h){return function(w){w.delegateTarget=s(w.target,f),w.delegateTarget&&h.call(l,w)}}o.exports=c},879:function(o,n){n.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},n.nodeList=function(i){var s=Object.prototype.toString.call(i);return i!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in i&&(i.length===0||n.node(i[0]))},n.string=function(i){return typeof i=="string"||i instanceof String},n.fn=function(i){var s=Object.prototype.toString.call(i);return s==="[object Function]"}},370:function(o,n,i){var s=i(879),a=i(438);function c(u,h,w){if(!u&&!h&&!w)throw new Error("Missing required arguments");if(!s.string(h))throw new TypeError("Second argument must be a String");if(!s.fn(w))throw new TypeError("Third argument must be a Function");if(s.node(u))return p(u,h,w);if(s.nodeList(u))return l(u,h,w);if(s.string(u))return f(u,h,w);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function p(u,h,w){return u.addEventListener(h,w),{destroy:function(){u.removeEventListener(h,w)}}}function l(u,h,w){return Array.prototype.forEach.call(u,function(A){A.addEventListener(h,w)}),{destroy:function(){Array.prototype.forEach.call(u,function(A){A.removeEventListener(h,w)})}}}function f(u,h,w){return a(document.body,u,h,w)}o.exports=c},817:function(o){function n(i){var s;if(i.nodeName==="SELECT")i.focus(),s=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var a=i.hasAttribute("readonly");a||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),a||i.removeAttribute("readonly"),s=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var c=window.getSelection(),p=document.createRange();p.selectNodeContents(i),c.removeAllRanges(),c.addRange(p),s=c.toString()}return s}o.exports=n},279:function(o){function n(){}n.prototype={on:function(i,s,a){var c=this.e||(this.e={});return(c[i]||(c[i]=[])).push({fn:s,ctx:a}),this},once:function(i,s,a){var c=this;function p(){c.off(i,p),s.apply(a,arguments)}return p._=s,this.on(i,p,a)},emit:function(i){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[i]||[]).slice(),c=0,p=a.length;for(c;c{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var Va=/["'&<>]/;qn.exports=za;function za(e){var t=""+e,r=Va.exec(t);if(!r)return t;var o,n="",i=0,s=0;for(i=r.index;i0&&i[i.length-1])&&(p[0]===6||p[0]===2)){r=0;continue}if(p[0]===3&&(!i||p[1]>i[0]&&p[1]=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function V(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var o=r.call(e),n,i=[],s;try{for(;(t===void 0||t-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(a){s={error:a}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(s)throw s.error}}return i}function z(e,t,r){if(r||arguments.length===2)for(var o=0,n=t.length,i;o1||a(u,h)})})}function a(u,h){try{c(o[u](h))}catch(w){f(i[0][3],w)}}function c(u){u.value instanceof ot?Promise.resolve(u.value.v).then(p,l):f(i[0][2],u)}function p(u){a("next",u)}function l(u){a("throw",u)}function f(u,h){u(h),i.shift(),i.length&&a(i[0][0],i[0][1])}}function so(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof ue=="function"?ue(e):e[Symbol.iterator](),r={},o("next"),o("throw"),o("return"),r[Symbol.asyncIterator]=function(){return this},r);function o(i){r[i]=e[i]&&function(s){return new Promise(function(a,c){s=e[i](s),n(a,c,s.done,s.value)})}}function n(i,s,a,c){Promise.resolve(c).then(function(p){i({value:p,done:a})},s)}}function k(e){return typeof e=="function"}function pt(e){var t=function(o){Error.call(o),o.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var Wt=pt(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(o,n){return n+1+") "+o.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Ve(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Ie=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,o,n,i;if(!this.closed){this.closed=!0;var s=this._parentage;if(s)if(this._parentage=null,Array.isArray(s))try{for(var a=ue(s),c=a.next();!c.done;c=a.next()){var p=c.value;p.remove(this)}}catch(A){t={error:A}}finally{try{c&&!c.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}else s.remove(this);var l=this.initialTeardown;if(k(l))try{l()}catch(A){i=A instanceof Wt?A.errors:[A]}var f=this._finalizers;if(f){this._finalizers=null;try{for(var u=ue(f),h=u.next();!h.done;h=u.next()){var w=h.value;try{co(w)}catch(A){i=i!=null?i:[],A instanceof Wt?i=z(z([],V(i)),V(A.errors)):i.push(A)}}}catch(A){o={error:A}}finally{try{h&&!h.done&&(n=u.return)&&n.call(u)}finally{if(o)throw o.error}}}if(i)throw new Wt(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)co(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Ve(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Ve(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Er=Ie.EMPTY;function Dt(e){return e instanceof Ie||e&&"closed"in e&&k(e.remove)&&k(e.add)&&k(e.unsubscribe)}function co(e){k(e)?e():e.unsubscribe()}var ke={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var lt={setTimeout:function(e,t){for(var r=[],o=2;o0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var o=this,n=this,i=n.hasError,s=n.isStopped,a=n.observers;return i||s?Er:(this.currentObservers=null,a.push(r),new Ie(function(){o.currentObservers=null,Ve(a,r)}))},t.prototype._checkFinalizedStatuses=function(r){var o=this,n=o.hasError,i=o.thrownError,s=o.isStopped;n?r.error(i):s&&r.complete()},t.prototype.asObservable=function(){var r=new j;return r.source=this,r},t.create=function(r,o){return new vo(r,o)},t}(j);var vo=function(e){se(t,e);function t(r,o){var n=e.call(this)||this;return n.destination=r,n.source=o,n}return t.prototype.next=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.next)===null||n===void 0||n.call(o,r)},t.prototype.error=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.error)===null||n===void 0||n.call(o,r)},t.prototype.complete=function(){var r,o;(o=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||o===void 0||o.call(r)},t.prototype._subscribe=function(r){var o,n;return(n=(o=this.source)===null||o===void 0?void 0:o.subscribe(r))!==null&&n!==void 0?n:Er},t}(v);var St={now:function(){return(St.delegate||Date).now()},delegate:void 0};var Ot=function(e){se(t,e);function t(r,o,n){r===void 0&&(r=1/0),o===void 0&&(o=1/0),n===void 0&&(n=St);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=o,i._timestampProvider=n,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=o===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,o),i}return t.prototype.next=function(r){var o=this,n=o.isStopped,i=o._buffer,s=o._infiniteTimeWindow,a=o._timestampProvider,c=o._windowTime;n||(i.push(r),!s&&i.push(a.now()+c)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var o=this._innerSubscribe(r),n=this,i=n._infiniteTimeWindow,s=n._buffer,a=s.slice(),c=0;c0?e.prototype.requestAsyncId.call(this,r,o,n):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,o,n){var i;if(n===void 0&&(n=0),n!=null?n>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,o,n);var s=r.actions;o!=null&&((i=s[s.length-1])===null||i===void 0?void 0:i.id)!==o&&(ut.cancelAnimationFrame(o),r._scheduled=void 0)},t}(zt);var yo=function(e){se(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var o=this._scheduled;this._scheduled=void 0;var n=this.actions,i;r=r||n.shift();do if(i=r.execute(r.state,r.delay))break;while((r=n[0])&&r.id===o&&n.shift());if(this._active=!1,i){for(;(r=n[0])&&r.id===o&&n.shift();)r.unsubscribe();throw i}},t}(qt);var de=new yo(xo);var L=new j(function(e){return e.complete()});function Kt(e){return e&&k(e.schedule)}function _r(e){return e[e.length-1]}function Je(e){return k(_r(e))?e.pop():void 0}function Ae(e){return Kt(_r(e))?e.pop():void 0}function Qt(e,t){return typeof _r(e)=="number"?e.pop():t}var dt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Yt(e){return k(e==null?void 0:e.then)}function Bt(e){return k(e[ft])}function Gt(e){return Symbol.asyncIterator&&k(e==null?void 0:e[Symbol.asyncIterator])}function Jt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Di(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Xt=Di();function Zt(e){return k(e==null?void 0:e[Xt])}function er(e){return ao(this,arguments,function(){var r,o,n,i;return Ut(this,function(s){switch(s.label){case 0:r=e.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,ot(r.read())];case 3:return o=s.sent(),n=o.value,i=o.done,i?[4,ot(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,ot(n)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function tr(e){return k(e==null?void 0:e.getReader)}function N(e){if(e instanceof j)return e;if(e!=null){if(Bt(e))return Ni(e);if(dt(e))return Vi(e);if(Yt(e))return zi(e);if(Gt(e))return Eo(e);if(Zt(e))return qi(e);if(tr(e))return Ki(e)}throw Jt(e)}function Ni(e){return new j(function(t){var r=e[ft]();if(k(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Vi(e){return new j(function(t){for(var r=0;r=2;return function(o){return o.pipe(e?g(function(n,i){return e(n,i,o)}):ce,ye(1),r?Qe(t):jo(function(){return new or}))}}function $r(e){return e<=0?function(){return L}:x(function(t,r){var o=[];t.subscribe(S(r,function(n){o.push(n),e=2,!0))}function le(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new v}:t,o=e.resetOnError,n=o===void 0?!0:o,i=e.resetOnComplete,s=i===void 0?!0:i,a=e.resetOnRefCountZero,c=a===void 0?!0:a;return function(p){var l,f,u,h=0,w=!1,A=!1,Z=function(){f==null||f.unsubscribe(),f=void 0},te=function(){Z(),l=u=void 0,w=A=!1},J=function(){var C=l;te(),C==null||C.unsubscribe()};return x(function(C,ct){h++,!A&&!w&&Z();var Ne=u=u!=null?u:r();ct.add(function(){h--,h===0&&!A&&!w&&(f=Pr(J,c))}),Ne.subscribe(ct),!l&&h>0&&(l=new it({next:function(Pe){return Ne.next(Pe)},error:function(Pe){A=!0,Z(),f=Pr(te,n,Pe),Ne.error(Pe)},complete:function(){w=!0,Z(),f=Pr(te,s),Ne.complete()}}),N(C).subscribe(l))})(p)}}function Pr(e,t){for(var r=[],o=2;oe.next(document)),e}function R(e,t=document){return Array.from(t.querySelectorAll(e))}function P(e,t=document){let r=me(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function me(e,t=document){return t.querySelector(e)||void 0}function Re(){var e,t,r,o;return(o=(r=(t=(e=document.activeElement)==null?void 0:e.shadowRoot)==null?void 0:t.activeElement)!=null?r:document.activeElement)!=null?o:void 0}var la=T(d(document.body,"focusin"),d(document.body,"focusout")).pipe(be(1),q(void 0),m(()=>Re()||document.body),B(1));function vt(e){return la.pipe(m(t=>e.contains(t)),Y())}function Vo(e,t){return T(d(e,"mouseenter").pipe(m(()=>!0)),d(e,"mouseleave").pipe(m(()=>!1))).pipe(t?be(t):ce,q(!1))}function Ue(e){return{x:e.offsetLeft,y:e.offsetTop}}function zo(e){return T(d(window,"load"),d(window,"resize")).pipe(Me(0,de),m(()=>Ue(e)),q(Ue(e)))}function ir(e){return{x:e.scrollLeft,y:e.scrollTop}}function et(e){return T(d(e,"scroll"),d(window,"resize")).pipe(Me(0,de),m(()=>ir(e)),q(ir(e)))}function qo(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)qo(e,r)}function E(e,t,...r){let o=document.createElement(e);if(t)for(let n of Object.keys(t))typeof t[n]!="undefined"&&(typeof t[n]!="boolean"?o.setAttribute(n,t[n]):o.setAttribute(n,""));for(let n of r)qo(o,n);return o}function ar(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function gt(e){let t=E("script",{src:e});return H(()=>(document.head.appendChild(t),T(d(t,"load"),d(t,"error").pipe(b(()=>Ar(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(m(()=>{}),_(()=>document.head.removeChild(t)),ye(1))))}var Ko=new v,ma=H(()=>typeof ResizeObserver=="undefined"?gt("https://unpkg.com/resize-observer-polyfill"):$(void 0)).pipe(m(()=>new ResizeObserver(e=>{for(let t of e)Ko.next(t)})),b(e=>T(qe,$(e)).pipe(_(()=>e.disconnect()))),B(1));function pe(e){return{width:e.offsetWidth,height:e.offsetHeight}}function Ee(e){return ma.pipe(y(t=>t.observe(e)),b(t=>Ko.pipe(g(({target:r})=>r===e),_(()=>t.unobserve(e)),m(()=>pe(e)))),q(pe(e)))}function xt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function sr(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var Qo=new v,fa=H(()=>$(new IntersectionObserver(e=>{for(let t of e)Qo.next(t)},{threshold:0}))).pipe(b(e=>T(qe,$(e)).pipe(_(()=>e.disconnect()))),B(1));function yt(e){return fa.pipe(y(t=>t.observe(e)),b(t=>Qo.pipe(g(({target:r})=>r===e),_(()=>t.unobserve(e)),m(({isIntersecting:r})=>r))))}function Yo(e,t=16){return et(e).pipe(m(({y:r})=>{let o=pe(e),n=xt(e);return r>=n.height-o.height-t}),Y())}var cr={drawer:P("[data-md-toggle=drawer]"),search:P("[data-md-toggle=search]")};function Bo(e){return cr[e].checked}function Be(e,t){cr[e].checked!==t&&cr[e].click()}function We(e){let t=cr[e];return d(t,"change").pipe(m(()=>t.checked),q(t.checked))}function ua(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function da(){return T(d(window,"compositionstart").pipe(m(()=>!0)),d(window,"compositionend").pipe(m(()=>!1))).pipe(q(!1))}function Go(){let e=d(window,"keydown").pipe(g(t=>!(t.metaKey||t.ctrlKey)),m(t=>({mode:Bo("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),g(({mode:t,type:r})=>{if(t==="global"){let o=Re();if(typeof o!="undefined")return!ua(o,r)}return!0}),le());return da().pipe(b(t=>t?L:e))}function ve(){return new URL(location.href)}function st(e,t=!1){if(G("navigation.instant")&&!t){let r=E("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function Jo(){return new v}function Xo(){return location.hash.slice(1)}function Zo(e){let t=E("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function ha(e){return T(d(window,"hashchange"),e).pipe(m(Xo),q(Xo()),g(t=>t.length>0),B(1))}function en(e){return ha(e).pipe(m(t=>me(`[id="${t}"]`)),g(t=>typeof t!="undefined"))}function At(e){let t=matchMedia(e);return nr(r=>t.addListener(()=>r(t.matches))).pipe(q(t.matches))}function tn(){let e=matchMedia("print");return T(d(window,"beforeprint").pipe(m(()=>!0)),d(window,"afterprint").pipe(m(()=>!1))).pipe(q(e.matches))}function Ur(e,t){return e.pipe(b(r=>r?t():L))}function Wr(e,t){return new j(r=>{let o=new XMLHttpRequest;return o.open("GET",`${e}`),o.responseType="blob",o.addEventListener("load",()=>{o.status>=200&&o.status<300?(r.next(o.response),r.complete()):r.error(new Error(o.statusText))}),o.addEventListener("error",()=>{r.error(new Error("Network error"))}),o.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(o.addEventListener("progress",n=>{var i;if(n.lengthComputable)t.progress$.next(n.loaded/n.total*100);else{let s=(i=o.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(n.loaded/+s*100)}}),t.progress$.next(5)),o.send(),()=>o.abort()})}function De(e,t){return Wr(e,t).pipe(b(r=>r.text()),m(r=>JSON.parse(r)),B(1))}function rn(e,t){let r=new DOMParser;return Wr(e,t).pipe(b(o=>o.text()),m(o=>r.parseFromString(o,"text/html")),B(1))}function on(e,t){let r=new DOMParser;return Wr(e,t).pipe(b(o=>o.text()),m(o=>r.parseFromString(o,"text/xml")),B(1))}function nn(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function an(){return T(d(window,"scroll",{passive:!0}),d(window,"resize",{passive:!0})).pipe(m(nn),q(nn()))}function sn(){return{width:innerWidth,height:innerHeight}}function cn(){return d(window,"resize",{passive:!0}).pipe(m(sn),q(sn()))}function pn(){return Q([an(),cn()]).pipe(m(([e,t])=>({offset:e,size:t})),B(1))}function pr(e,{viewport$:t,header$:r}){let o=t.pipe(X("size")),n=Q([o,r]).pipe(m(()=>Ue(e)));return Q([r,t,n]).pipe(m(([{height:i},{offset:s,size:a},{x:c,y:p}])=>({offset:{x:s.x-c,y:s.y-p+i},size:a})))}function ba(e){return d(e,"message",t=>t.data)}function va(e){let t=new v;return t.subscribe(r=>e.postMessage(r)),t}function ln(e,t=new Worker(e)){let r=ba(t),o=va(t),n=new v;n.subscribe(o);let i=o.pipe(ee(),oe(!0));return n.pipe(ee(),$e(r.pipe(U(i))),le())}var ga=P("#__config"),Et=JSON.parse(ga.textContent);Et.base=`${new URL(Et.base,ve())}`;function we(){return Et}function G(e){return Et.features.includes(e)}function ge(e,t){return typeof t!="undefined"?Et.translations[e].replace("#",t.toString()):Et.translations[e]}function Te(e,t=document){return P(`[data-md-component=${e}]`,t)}function ne(e,t=document){return R(`[data-md-component=${e}]`,t)}function xa(e){let t=P(".md-typeset > :first-child",e);return d(t,"click",{once:!0}).pipe(m(()=>P(".md-typeset",e)),m(r=>({hash:__md_hash(r.innerHTML)})))}function mn(e){if(!G("announce.dismiss")||!e.childElementCount)return L;if(!e.hidden){let t=P(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return H(()=>{let t=new v;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),xa(e).pipe(y(r=>t.next(r)),_(()=>t.complete()),m(r=>F({ref:e},r)))})}function ya(e,{target$:t}){return t.pipe(m(r=>({hidden:r!==e})))}function fn(e,t){let r=new v;return r.subscribe(({hidden:o})=>{e.hidden=o}),ya(e,t).pipe(y(o=>r.next(o)),_(()=>r.complete()),m(o=>F({ref:e},o)))}function Ct(e,t){return t==="inline"?E("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},E("div",{class:"md-tooltip__inner md-typeset"})):E("div",{class:"md-tooltip",id:e,role:"tooltip"},E("div",{class:"md-tooltip__inner md-typeset"}))}function un(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return E("aside",{class:"md-annotation",tabIndex:0},Ct(t),E("a",{href:r,class:"md-annotation__index",tabIndex:-1},E("span",{"data-md-annotation-id":e})))}else return E("aside",{class:"md-annotation",tabIndex:0},Ct(t),E("span",{class:"md-annotation__index",tabIndex:-1},E("span",{"data-md-annotation-id":e})))}function dn(e){return E("button",{class:"md-clipboard md-icon",title:ge("clipboard.copy"),"data-clipboard-target":`#${e} > code`})}function Dr(e,t){let r=t&2,o=t&1,n=Object.keys(e.terms).filter(c=>!e.terms[c]).reduce((c,p)=>[...c,E("del",null,p)," "],[]).slice(0,-1),i=we(),s=new URL(e.location,i.base);G("search.highlight")&&s.searchParams.set("h",Object.entries(e.terms).filter(([,c])=>c).reduce((c,[p])=>`${c} ${p}`.trim(),""));let{tags:a}=we();return E("a",{href:`${s}`,class:"md-search-result__link",tabIndex:-1},E("article",{class:"md-search-result__article md-typeset","data-md-score":e.score.toFixed(2)},r>0&&E("div",{class:"md-search-result__icon md-icon"}),r>0&&E("h1",null,e.title),r<=0&&E("h2",null,e.title),o>0&&e.text.length>0&&e.text,e.tags&&e.tags.map(c=>{let p=a?c in a?`md-tag-icon md-tag--${a[c]}`:"md-tag-icon":"";return E("span",{class:`md-tag ${p}`},c)}),o>0&&n.length>0&&E("p",{class:"md-search-result__terms"},ge("search.result.term.missing"),": ",...n)))}function hn(e){let t=e[0].score,r=[...e],o=we(),n=r.findIndex(l=>!`${new URL(l.location,o.base)}`.includes("#")),[i]=r.splice(n,1),s=r.findIndex(l=>l.scoreDr(l,1)),...c.length?[E("details",{class:"md-search-result__more"},E("summary",{tabIndex:-1},E("div",null,c.length>0&&c.length===1?ge("search.result.more.one"):ge("search.result.more.other",c.length))),...c.map(l=>Dr(l,1)))]:[]];return E("li",{class:"md-search-result__item"},p)}function bn(e){return E("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>E("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?ar(r):r)))}function Nr(e){let t=`tabbed-control tabbed-control--${e}`;return E("div",{class:t,hidden:!0},E("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function vn(e){return E("div",{class:"md-typeset__scrollwrap"},E("div",{class:"md-typeset__table"},e))}function Ea(e){let t=we(),r=new URL(`../${e.version}/`,t.base);return E("li",{class:"md-version__item"},E("a",{href:`${r}`,class:"md-version__link"},e.title))}function gn(e,t){return E("div",{class:"md-version"},E("button",{class:"md-version__current","aria-label":ge("select.version")},t.title),E("ul",{class:"md-version__list"},e.map(Ea)))}var wa=0;function Ta(e,t){document.body.append(e);let{width:r}=pe(e);e.style.setProperty("--md-tooltip-width",`${r}px`),e.remove();let o=sr(t),n=typeof o!="undefined"?et(o):$({x:0,y:0}),i=T(vt(t),Vo(t)).pipe(Y());return Q([i,n]).pipe(m(([s,a])=>{let{x:c,y:p}=Ue(t),l=pe(t),f=t.closest("table");return f&&t.parentElement&&(c+=f.offsetLeft+t.parentElement.offsetLeft,p+=f.offsetTop+t.parentElement.offsetTop),{active:s,offset:{x:c-a.x+l.width/2-r/2,y:p-a.y+l.height+8}}}))}function Ge(e){let t=e.title;if(!t.length)return L;let r=`__tooltip_${wa++}`,o=Ct(r,"inline"),n=P(".md-typeset",o);return n.innerHTML=t,H(()=>{let i=new v;return i.subscribe({next({offset:s}){o.style.setProperty("--md-tooltip-x",`${s.x}px`),o.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){o.style.removeProperty("--md-tooltip-x"),o.style.removeProperty("--md-tooltip-y")}}),T(i.pipe(g(({active:s})=>s)),i.pipe(be(250),g(({active:s})=>!s))).subscribe({next({active:s}){s?(e.insertAdjacentElement("afterend",o),e.setAttribute("aria-describedby",r),e.removeAttribute("title")):(o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t))},complete(){o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t)}}),i.pipe(Me(16,de)).subscribe(({active:s})=>{o.classList.toggle("md-tooltip--active",s)}),i.pipe(_t(125,de),g(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:s})=>s)).subscribe({next(s){s?o.style.setProperty("--md-tooltip-0",`${-s}px`):o.style.removeProperty("--md-tooltip-0")},complete(){o.style.removeProperty("--md-tooltip-0")}}),Ta(o,e).pipe(y(s=>i.next(s)),_(()=>i.complete()),m(s=>F({ref:e},s)))}).pipe(ze(ie))}function Sa(e,t){let r=H(()=>Q([zo(e),et(t)])).pipe(m(([{x:o,y:n},i])=>{let{width:s,height:a}=pe(e);return{x:o-i.x+s/2,y:n-i.y+a/2}}));return vt(e).pipe(b(o=>r.pipe(m(n=>({active:o,offset:n})),ye(+!o||1/0))))}function xn(e,t,{target$:r}){let[o,n]=Array.from(e.children);return H(()=>{let i=new v,s=i.pipe(ee(),oe(!0));return i.subscribe({next({offset:a}){e.style.setProperty("--md-tooltip-x",`${a.x}px`),e.style.setProperty("--md-tooltip-y",`${a.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),yt(e).pipe(U(s)).subscribe(a=>{e.toggleAttribute("data-md-visible",a)}),T(i.pipe(g(({active:a})=>a)),i.pipe(be(250),g(({active:a})=>!a))).subscribe({next({active:a}){a?e.prepend(o):o.remove()},complete(){e.prepend(o)}}),i.pipe(Me(16,de)).subscribe(({active:a})=>{o.classList.toggle("md-tooltip--active",a)}),i.pipe(_t(125,de),g(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:a})=>a)).subscribe({next(a){a?e.style.setProperty("--md-tooltip-0",`${-a}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),d(n,"click").pipe(U(s),g(a=>!(a.metaKey||a.ctrlKey))).subscribe(a=>{a.stopPropagation(),a.preventDefault()}),d(n,"mousedown").pipe(U(s),ae(i)).subscribe(([a,{active:c}])=>{var p;if(a.button!==0||a.metaKey||a.ctrlKey)a.preventDefault();else if(c){a.preventDefault();let l=e.parentElement.closest(".md-annotation");l instanceof HTMLElement?l.focus():(p=Re())==null||p.blur()}}),r.pipe(U(s),g(a=>a===o),Ye(125)).subscribe(()=>e.focus()),Sa(e,t).pipe(y(a=>i.next(a)),_(()=>i.complete()),m(a=>F({ref:e},a)))})}function Oa(e){return e.tagName==="CODE"?R(".c, .c1, .cm",e):[e]}function Ma(e){let t=[];for(let r of Oa(e)){let o=[],n=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=n.nextNode();i;i=n.nextNode())o.push(i);for(let i of o){let s;for(;s=/(\(\d+\))(!)?/.exec(i.textContent);){let[,a,c]=s;if(typeof c=="undefined"){let p=i.splitText(s.index);i=p.splitText(a.length),t.push(p)}else{i.textContent=a,t.push(i);break}}}}return t}function yn(e,t){t.append(...Array.from(e.childNodes))}function lr(e,t,{target$:r,print$:o}){let n=t.closest("[id]"),i=n==null?void 0:n.id,s=new Map;for(let a of Ma(t)){let[,c]=a.textContent.match(/\((\d+)\)/);me(`:scope > li:nth-child(${c})`,e)&&(s.set(c,un(c,i)),a.replaceWith(s.get(c)))}return s.size===0?L:H(()=>{let a=new v,c=a.pipe(ee(),oe(!0)),p=[];for(let[l,f]of s)p.push([P(".md-typeset",f),P(`:scope > li:nth-child(${l})`,e)]);return o.pipe(U(c)).subscribe(l=>{e.hidden=!l,e.classList.toggle("md-annotation-list",l);for(let[f,u]of p)l?yn(f,u):yn(u,f)}),T(...[...s].map(([,l])=>xn(l,t,{target$:r}))).pipe(_(()=>a.complete()),le())})}function En(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return En(t)}}function wn(e,t){return H(()=>{let r=En(e);return typeof r!="undefined"?lr(r,e,t):L})}var Tn=jt(zr());var La=0;function Sn(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return Sn(t)}}function _a(e){return Ee(e).pipe(m(({width:t})=>({scrollable:xt(e).width>t})),X("scrollable"))}function On(e,t){let{matches:r}=matchMedia("(hover)"),o=H(()=>{let n=new v,i=n.pipe($r(1));n.subscribe(({scrollable:c})=>{c&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let s=[];if(Tn.default.isSupported()&&(e.closest(".copy")||G("content.code.copy")&&!e.closest(".no-copy"))){let c=e.closest("pre");c.id=`__code_${La++}`;let p=dn(c.id);c.insertBefore(p,e),G("content.tooltips")&&s.push(Ge(p))}let a=e.closest(".highlight");if(a instanceof HTMLElement){let c=Sn(a);if(typeof c!="undefined"&&(a.classList.contains("annotate")||G("content.code.annotate"))){let p=lr(c,e,t);s.push(Ee(a).pipe(U(i),m(({width:l,height:f})=>l&&f),Y(),b(l=>l?p:L)))}}return _a(e).pipe(y(c=>n.next(c)),_(()=>n.complete()),m(c=>F({ref:e},c)),$e(...s))});return G("content.lazy")?yt(e).pipe(g(n=>n),ye(1),b(()=>o)):o}function Aa(e,{target$:t,print$:r}){let o=!0;return T(t.pipe(m(n=>n.closest("details:not([open])")),g(n=>e===n),m(()=>({action:"open",reveal:!0}))),r.pipe(g(n=>n||!o),y(()=>o=e.open),m(n=>({action:n?"open":"close"}))))}function Mn(e,t){return H(()=>{let r=new v;return r.subscribe(({action:o,reveal:n})=>{e.toggleAttribute("open",o==="open"),n&&e.scrollIntoView()}),Aa(e,t).pipe(y(o=>r.next(o)),_(()=>r.complete()),m(o=>F({ref:e},o)))})}var Ln=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel rect,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel rect{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color);stroke-width:.05rem}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs #classDiagram-compositionEnd,defs #classDiagram-compositionStart,defs #classDiagram-dependencyEnd,defs #classDiagram-dependencyStart,defs #classDiagram-extensionEnd,defs #classDiagram-extensionStart{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs #classDiagram-aggregationEnd,defs #classDiagram-aggregationStart{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}.attributeBoxEven,.attributeBoxOdd{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityBox{fill:var(--md-mermaid-label-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityLabel{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.relationshipLabelBox{fill:var(--md-mermaid-label-bg-color);fill-opacity:1;background-color:var(--md-mermaid-label-bg-color);opacity:1}.relationshipLabel{fill:var(--md-mermaid-label-fg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs #ONE_OR_MORE_END *,defs #ONE_OR_MORE_START *,defs #ONLY_ONE_END *,defs #ONLY_ONE_START *,defs #ZERO_OR_MORE_END *,defs #ZERO_OR_MORE_START *,defs #ZERO_OR_ONE_END *,defs #ZERO_OR_ONE_START *{stroke:var(--md-mermaid-edge-color)!important}defs #ZERO_OR_MORE_END circle,defs #ZERO_OR_MORE_START circle{fill:var(--md-mermaid-label-bg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var qr,ka=0;function Ha(){return typeof mermaid=="undefined"||mermaid instanceof Element?gt("https://unpkg.com/mermaid@10.7.0/dist/mermaid.min.js"):$(void 0)}function _n(e){return e.classList.remove("mermaid"),qr||(qr=Ha().pipe(y(()=>mermaid.initialize({startOnLoad:!1,themeCSS:Ln,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),m(()=>{}),B(1))),qr.subscribe(()=>ro(this,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${ka++}`,r=E("div",{class:"mermaid"}),o=e.textContent,{svg:n,fn:i}=yield mermaid.render(t,o),s=r.attachShadow({mode:"closed"});s.innerHTML=n,e.replaceWith(r),i==null||i(s)})),qr.pipe(m(()=>({ref:e})))}var An=E("table");function Cn(e){return e.replaceWith(An),An.replaceWith(vn(e)),$({ref:e})}function $a(e){let t=e.find(r=>r.checked)||e[0];return T(...e.map(r=>d(r,"change").pipe(m(()=>P(`label[for="${r.id}"]`))))).pipe(q(P(`label[for="${t.id}"]`)),m(r=>({active:r})))}function kn(e,{viewport$:t,target$:r}){let o=P(".tabbed-labels",e),n=R(":scope > input",e),i=Nr("prev");e.append(i);let s=Nr("next");return e.append(s),H(()=>{let a=new v,c=a.pipe(ee(),oe(!0));Q([a,Ee(e)]).pipe(U(c),Me(1,de)).subscribe({next([{active:p},l]){let f=Ue(p),{width:u}=pe(p);e.style.setProperty("--md-indicator-x",`${f.x}px`),e.style.setProperty("--md-indicator-width",`${u}px`);let h=ir(o);(f.xh.x+l.width)&&o.scrollTo({left:Math.max(0,f.x-16),behavior:"smooth"})},complete(){e.style.removeProperty("--md-indicator-x"),e.style.removeProperty("--md-indicator-width")}}),Q([et(o),Ee(o)]).pipe(U(c)).subscribe(([p,l])=>{let f=xt(o);i.hidden=p.x<16,s.hidden=p.x>f.width-l.width-16}),T(d(i,"click").pipe(m(()=>-1)),d(s,"click").pipe(m(()=>1))).pipe(U(c)).subscribe(p=>{let{width:l}=pe(o);o.scrollBy({left:l*p,behavior:"smooth"})}),r.pipe(U(c),g(p=>n.includes(p))).subscribe(p=>p.click()),o.classList.add("tabbed-labels--linked");for(let p of n){let l=P(`label[for="${p.id}"]`);l.replaceChildren(E("a",{href:`#${l.htmlFor}`,tabIndex:-1},...Array.from(l.childNodes))),d(l.firstElementChild,"click").pipe(U(c),g(f=>!(f.metaKey||f.ctrlKey)),y(f=>{f.preventDefault(),f.stopPropagation()})).subscribe(()=>{history.replaceState({},"",`#${l.htmlFor}`),l.click()})}return G("content.tabs.link")&&a.pipe(Le(1),ae(t)).subscribe(([{active:p},{offset:l}])=>{let f=p.innerText.trim();if(p.hasAttribute("data-md-switching"))p.removeAttribute("data-md-switching");else{let u=e.offsetTop-l.y;for(let w of R("[data-tabs]"))for(let A of R(":scope > input",w)){let Z=P(`label[for="${A.id}"]`);if(Z!==p&&Z.innerText.trim()===f){Z.setAttribute("data-md-switching",""),A.click();break}}window.scrollTo({top:e.offsetTop-u});let h=__md_get("__tabs")||[];__md_set("__tabs",[...new Set([f,...h])])}}),a.pipe(U(c)).subscribe(()=>{for(let p of R("audio, video",e))p.pause()}),$a(n).pipe(y(p=>a.next(p)),_(()=>a.complete()),m(p=>F({ref:e},p)))}).pipe(ze(ie))}function Hn(e,{viewport$:t,target$:r,print$:o}){return T(...R(".annotate:not(.highlight)",e).map(n=>wn(n,{target$:r,print$:o})),...R("pre:not(.mermaid) > code",e).map(n=>On(n,{target$:r,print$:o})),...R("pre.mermaid",e).map(n=>_n(n)),...R("table:not([class])",e).map(n=>Cn(n)),...R("details",e).map(n=>Mn(n,{target$:r,print$:o})),...R("[data-tabs]",e).map(n=>kn(n,{viewport$:t,target$:r})),...R("[title]",e).filter(()=>G("content.tooltips")).map(n=>Ge(n)))}function Ra(e,{alert$:t}){return t.pipe(b(r=>T($(!0),$(!1).pipe(Ye(2e3))).pipe(m(o=>({message:r,active:o})))))}function $n(e,t){let r=P(".md-typeset",e);return H(()=>{let o=new v;return o.subscribe(({message:n,active:i})=>{e.classList.toggle("md-dialog--active",i),r.textContent=n}),Ra(e,t).pipe(y(n=>o.next(n)),_(()=>o.complete()),m(n=>F({ref:e},n)))})}function Pa({viewport$:e}){if(!G("header.autohide"))return $(!1);let t=e.pipe(m(({offset:{y:n}})=>n),Ke(2,1),m(([n,i])=>[nMath.abs(i-n.y)>100),m(([,[n]])=>n),Y()),o=We("search");return Q([e,o]).pipe(m(([{offset:n},i])=>n.y>400&&!i),Y(),b(n=>n?r:$(!1)),q(!1))}function Rn(e,t){return H(()=>Q([Ee(e),Pa(t)])).pipe(m(([{height:r},o])=>({height:r,hidden:o})),Y((r,o)=>r.height===o.height&&r.hidden===o.hidden),B(1))}function Pn(e,{header$:t,main$:r}){return H(()=>{let o=new v,n=o.pipe(ee(),oe(!0));o.pipe(X("active"),je(t)).subscribe(([{active:s},{hidden:a}])=>{e.classList.toggle("md-header--shadow",s&&!a),e.hidden=a});let i=fe(R("[title]",e)).pipe(g(()=>G("content.tooltips")),re(s=>Ge(s)));return r.subscribe(o),t.pipe(U(n),m(s=>F({ref:e},s)),$e(i.pipe(U(n))))})}function Ia(e,{viewport$:t,header$:r}){return pr(e,{viewport$:t,header$:r}).pipe(m(({offset:{y:o}})=>{let{height:n}=pe(e);return{active:o>=n}}),X("active"))}function In(e,t){return H(()=>{let r=new v;r.subscribe({next({active:n}){e.classList.toggle("md-header__title--active",n)},complete(){e.classList.remove("md-header__title--active")}});let o=me(".md-content h1");return typeof o=="undefined"?L:Ia(o,t).pipe(y(n=>r.next(n)),_(()=>r.complete()),m(n=>F({ref:e},n)))})}function Fn(e,{viewport$:t,header$:r}){let o=r.pipe(m(({height:i})=>i),Y()),n=o.pipe(b(()=>Ee(e).pipe(m(({height:i})=>({top:e.offsetTop,bottom:e.offsetTop+i})),X("bottom"))));return Q([o,n,t]).pipe(m(([i,{top:s,bottom:a},{offset:{y:c},size:{height:p}}])=>(p=Math.max(0,p-Math.max(0,s-c,i)-Math.max(0,p+c-a)),{offset:s-i,height:p,active:s-i<=c})),Y((i,s)=>i.offset===s.offset&&i.height===s.height&&i.active===s.active))}function Fa(e){let t=__md_get("__palette")||{index:e.findIndex(o=>matchMedia(o.getAttribute("data-md-color-media")).matches)},r=Math.max(0,Math.min(t.index,e.length-1));return $(...e).pipe(re(o=>d(o,"change").pipe(m(()=>o))),q(e[r]),m(o=>({index:e.indexOf(o),color:{media:o.getAttribute("data-md-color-media"),scheme:o.getAttribute("data-md-color-scheme"),primary:o.getAttribute("data-md-color-primary"),accent:o.getAttribute("data-md-color-accent")}})),B(1))}function jn(e){let t=R("input",e),r=E("meta",{name:"theme-color"});document.head.appendChild(r);let o=E("meta",{name:"color-scheme"});document.head.appendChild(o);let n=At("(prefers-color-scheme: light)");return H(()=>{let i=new v;return i.subscribe(s=>{if(document.body.setAttribute("data-md-color-switching",""),s.color.media==="(prefers-color-scheme)"){let a=matchMedia("(prefers-color-scheme: light)"),c=document.querySelector(a.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");s.color.scheme=c.getAttribute("data-md-color-scheme"),s.color.primary=c.getAttribute("data-md-color-primary"),s.color.accent=c.getAttribute("data-md-color-accent")}for(let[a,c]of Object.entries(s.color))document.body.setAttribute(`data-md-color-${a}`,c);for(let a=0;a{let s=Te("header"),a=window.getComputedStyle(s);return o.content=a.colorScheme,a.backgroundColor.match(/\d+/g).map(c=>(+c).toString(16).padStart(2,"0")).join("")})).subscribe(s=>r.content=`#${s}`),i.pipe(Oe(ie)).subscribe(()=>{document.body.removeAttribute("data-md-color-switching")}),Fa(t).pipe(U(n.pipe(Le(1))),at(),y(s=>i.next(s)),_(()=>i.complete()),m(s=>F({ref:e},s)))})}function Un(e,{progress$:t}){return H(()=>{let r=new v;return r.subscribe(({value:o})=>{e.style.setProperty("--md-progress-value",`${o}`)}),t.pipe(y(o=>r.next({value:o})),_(()=>r.complete()),m(o=>({ref:e,value:o})))})}var Kr=jt(zr());function ja(e){e.setAttribute("data-md-copying","");let t=e.closest("[data-copy]"),r=t?t.getAttribute("data-copy"):e.innerText;return e.removeAttribute("data-md-copying"),r.trimEnd()}function Wn({alert$:e}){Kr.default.isSupported()&&new j(t=>{new Kr.default("[data-clipboard-target], [data-clipboard-text]",{text:r=>r.getAttribute("data-clipboard-text")||ja(P(r.getAttribute("data-clipboard-target")))}).on("success",r=>t.next(r))}).pipe(y(t=>{t.trigger.focus()}),m(()=>ge("clipboard.copied"))).subscribe(e)}function Dn(e,t){return e.protocol=t.protocol,e.hostname=t.hostname,e}function Ua(e,t){let r=new Map;for(let o of R("url",e)){let n=P("loc",o),i=[Dn(new URL(n.textContent),t)];r.set(`${i[0]}`,i);for(let s of R("[rel=alternate]",o)){let a=s.getAttribute("href");a!=null&&i.push(Dn(new URL(a),t))}}return r}function mr(e){return on(new URL("sitemap.xml",e)).pipe(m(t=>Ua(t,new URL(e))),he(()=>$(new Map)))}function Wa(e,t){if(!(e.target instanceof Element))return L;let r=e.target.closest("a");if(r===null)return L;if(r.target||e.metaKey||e.ctrlKey)return L;let o=new URL(r.href);return o.search=o.hash="",t.has(`${o}`)?(e.preventDefault(),$(new URL(r.href))):L}function Nn(e){let t=new Map;for(let r of R(":scope > *",e.head))t.set(r.outerHTML,r);return t}function Vn(e){for(let t of R("[href], [src]",e))for(let r of["href","src"]){let o=t.getAttribute(r);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){t[r]=t[r];break}}return $(e)}function Da(e){for(let o of["[data-md-component=announce]","[data-md-component=container]","[data-md-component=header-topic]","[data-md-component=outdated]","[data-md-component=logo]","[data-md-component=skip]",...G("navigation.tabs.sticky")?["[data-md-component=tabs]"]:[]]){let n=me(o),i=me(o,e);typeof n!="undefined"&&typeof i!="undefined"&&n.replaceWith(i)}let t=Nn(document);for(let[o,n]of Nn(e))t.has(o)?t.delete(o):document.head.appendChild(n);for(let o of t.values()){let n=o.getAttribute("name");n!=="theme-color"&&n!=="color-scheme"&&o.remove()}let r=Te("container");return Fe(R("script",r)).pipe(b(o=>{let n=e.createElement("script");if(o.src){for(let i of o.getAttributeNames())n.setAttribute(i,o.getAttribute(i));return o.replaceWith(n),new j(i=>{n.onload=()=>i.complete()})}else return n.textContent=o.textContent,o.replaceWith(n),L}),ee(),oe(document))}function zn({location$:e,viewport$:t,progress$:r}){let o=we();if(location.protocol==="file:")return L;let n=mr(o.base);$(document).subscribe(Vn);let i=d(document.body,"click").pipe(je(n),b(([c,p])=>Wa(c,p)),le()),s=d(window,"popstate").pipe(m(ve),le());i.pipe(ae(t)).subscribe(([c,{offset:p}])=>{history.replaceState(p,""),history.pushState(null,"",c)}),T(i,s).subscribe(e);let a=e.pipe(X("pathname"),b(c=>rn(c,{progress$:r}).pipe(he(()=>(st(c,!0),L)))),b(Vn),b(Da),le());return T(a.pipe(ae(e,(c,p)=>p)),e.pipe(X("pathname"),b(()=>e),X("hash")),e.pipe(Y((c,p)=>c.pathname===p.pathname&&c.hash===p.hash),b(()=>i),y(()=>history.back()))).subscribe(c=>{var p,l;history.state!==null||!c.hash?window.scrollTo(0,(l=(p=history.state)==null?void 0:p.y)!=null?l:0):(history.scrollRestoration="auto",Zo(c.hash),history.scrollRestoration="manual")}),e.subscribe(()=>{history.scrollRestoration="manual"}),d(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}),t.pipe(X("offset"),be(100)).subscribe(({offset:c})=>{history.replaceState(c,"")}),a}var Qn=jt(Kn());function Yn(e){let t=e.separator.split("|").map(n=>n.replace(/(\(\?[!=<][^)]+\))/g,"").length===0?"\uFFFD":n).join("|"),r=new RegExp(t,"img"),o=(n,i,s)=>`${i}${s}`;return n=>{n=n.replace(/[\s*+\-:~^]+/g," ").trim();let i=new RegExp(`(^|${e.separator}|)(${n.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(r,"|")})`,"img");return s=>(0,Qn.default)(s).replace(i,o).replace(/<\/mark>(\s+)]*>/img,"$1")}}function Ht(e){return e.type===1}function fr(e){return e.type===3}function Bn(e,t){let r=ln(e);return T($(location.protocol!=="file:"),We("search")).pipe(He(o=>o),b(()=>t)).subscribe(({config:o,docs:n})=>r.next({type:0,data:{config:o,docs:n,options:{suggest:G("search.suggest")}}})),r}function Gn({document$:e}){let t=we(),r=De(new URL("../versions.json",t.base)).pipe(he(()=>L)),o=r.pipe(m(n=>{let[,i]=t.base.match(/([^/]+)\/?$/);return n.find(({version:s,aliases:a})=>s===i||a.includes(i))||n[0]}));r.pipe(m(n=>new Map(n.map(i=>[`${new URL(`../${i.version}/`,t.base)}`,i]))),b(n=>d(document.body,"click").pipe(g(i=>!i.metaKey&&!i.ctrlKey),ae(o),b(([i,s])=>{if(i.target instanceof Element){let a=i.target.closest("a");if(a&&!a.target&&n.has(a.href)){let c=a.href;return!i.target.closest(".md-version")&&n.get(c)===s?L:(i.preventDefault(),$(c))}}return L}),b(i=>{let{version:s}=n.get(i);return mr(new URL(i)).pipe(m(a=>{let p=ve().href.replace(t.base,"");return a.has(p.split("#")[0])?new URL(`../${s}/${p}`,t.base):new URL(i)}))})))).subscribe(n=>st(n,!0)),Q([r,o]).subscribe(([n,i])=>{P(".md-header__topic").appendChild(gn(n,i))}),e.pipe(b(()=>o)).subscribe(n=>{var s;let i=__md_get("__outdated",sessionStorage);if(i===null){i=!0;let a=((s=t.version)==null?void 0:s.default)||"latest";Array.isArray(a)||(a=[a]);e:for(let c of a)for(let p of n.aliases.concat(n.version))if(new RegExp(c,"i").test(p)){i=!1;break e}__md_set("__outdated",i,sessionStorage)}if(i)for(let a of ne("outdated"))a.hidden=!1})}function Ka(e,{worker$:t}){let{searchParams:r}=ve();r.has("q")&&(Be("search",!0),e.value=r.get("q"),e.focus(),We("search").pipe(He(i=>!i)).subscribe(()=>{let i=ve();i.searchParams.delete("q"),history.replaceState({},"",`${i}`)}));let o=vt(e),n=T(t.pipe(He(Ht)),d(e,"keyup"),o).pipe(m(()=>e.value),Y());return Q([n,o]).pipe(m(([i,s])=>({value:i,focus:s})),B(1))}function Jn(e,{worker$:t}){let r=new v,o=r.pipe(ee(),oe(!0));Q([t.pipe(He(Ht)),r],(i,s)=>s).pipe(X("value")).subscribe(({value:i})=>t.next({type:2,data:i})),r.pipe(X("focus")).subscribe(({focus:i})=>{i&&Be("search",i)}),d(e.form,"reset").pipe(U(o)).subscribe(()=>e.focus());let n=P("header [for=__search]");return d(n,"click").subscribe(()=>e.focus()),Ka(e,{worker$:t}).pipe(y(i=>r.next(i)),_(()=>r.complete()),m(i=>F({ref:e},i)),B(1))}function Xn(e,{worker$:t,query$:r}){let o=new v,n=Yo(e.parentElement).pipe(g(Boolean)),i=e.parentElement,s=P(":scope > :first-child",e),a=P(":scope > :last-child",e);We("search").subscribe(l=>a.setAttribute("role",l?"list":"presentation")),o.pipe(ae(r),Ir(t.pipe(He(Ht)))).subscribe(([{items:l},{value:f}])=>{switch(l.length){case 0:s.textContent=f.length?ge("search.result.none"):ge("search.result.placeholder");break;case 1:s.textContent=ge("search.result.one");break;default:let u=ar(l.length);s.textContent=ge("search.result.other",u)}});let c=o.pipe(y(()=>a.innerHTML=""),b(({items:l})=>T($(...l.slice(0,10)),$(...l.slice(10)).pipe(Ke(4),jr(n),b(([f])=>f)))),m(hn),le());return c.subscribe(l=>a.appendChild(l)),c.pipe(re(l=>{let f=me("details",l);return typeof f=="undefined"?L:d(f,"toggle").pipe(U(o),m(()=>f))})).subscribe(l=>{l.open===!1&&l.offsetTop<=i.scrollTop&&i.scrollTo({top:l.offsetTop})}),t.pipe(g(fr),m(({data:l})=>l)).pipe(y(l=>o.next(l)),_(()=>o.complete()),m(l=>F({ref:e},l)))}function Qa(e,{query$:t}){return t.pipe(m(({value:r})=>{let o=ve();return o.hash="",r=r.replace(/\s+/g,"+").replace(/&/g,"%26").replace(/=/g,"%3D"),o.search=`q=${r}`,{url:o}}))}function Zn(e,t){let r=new v,o=r.pipe(ee(),oe(!0));return r.subscribe(({url:n})=>{e.setAttribute("data-clipboard-text",e.href),e.href=`${n}`}),d(e,"click").pipe(U(o)).subscribe(n=>n.preventDefault()),Qa(e,t).pipe(y(n=>r.next(n)),_(()=>r.complete()),m(n=>F({ref:e},n)))}function ei(e,{worker$:t,keyboard$:r}){let o=new v,n=Te("search-query"),i=T(d(n,"keydown"),d(n,"focus")).pipe(Oe(ie),m(()=>n.value),Y());return o.pipe(je(i),m(([{suggest:a},c])=>{let p=c.split(/([\s-]+)/);if(a!=null&&a.length&&p[p.length-1]){let l=a[a.length-1];l.startsWith(p[p.length-1])&&(p[p.length-1]=l)}else p.length=0;return p})).subscribe(a=>e.innerHTML=a.join("").replace(/\s/g," ")),r.pipe(g(({mode:a})=>a==="search")).subscribe(a=>{switch(a.type){case"ArrowRight":e.innerText.length&&n.selectionStart===n.value.length&&(n.value=e.innerText);break}}),t.pipe(g(fr),m(({data:a})=>a)).pipe(y(a=>o.next(a)),_(()=>o.complete()),m(()=>({ref:e})))}function ti(e,{index$:t,keyboard$:r}){let o=we();try{let n=Bn(o.search,t),i=Te("search-query",e),s=Te("search-result",e);d(e,"click").pipe(g(({target:c})=>c instanceof Element&&!!c.closest("a"))).subscribe(()=>Be("search",!1)),r.pipe(g(({mode:c})=>c==="search")).subscribe(c=>{let p=Re();switch(c.type){case"Enter":if(p===i){let l=new Map;for(let f of R(":first-child [href]",s)){let u=f.firstElementChild;l.set(f,parseFloat(u.getAttribute("data-md-score")))}if(l.size){let[[f]]=[...l].sort(([,u],[,h])=>h-u);f.click()}c.claim()}break;case"Escape":case"Tab":Be("search",!1),i.blur();break;case"ArrowUp":case"ArrowDown":if(typeof p=="undefined")i.focus();else{let l=[i,...R(":not(details) > [href], summary, details[open] [href]",s)],f=Math.max(0,(Math.max(0,l.indexOf(p))+l.length+(c.type==="ArrowUp"?-1:1))%l.length);l[f].focus()}c.claim();break;default:i!==Re()&&i.focus()}}),r.pipe(g(({mode:c})=>c==="global")).subscribe(c=>{switch(c.type){case"f":case"s":case"/":i.focus(),i.select(),c.claim();break}});let a=Jn(i,{worker$:n});return T(a,Xn(s,{worker$:n,query$:a})).pipe($e(...ne("search-share",e).map(c=>Zn(c,{query$:a})),...ne("search-suggest",e).map(c=>ei(c,{worker$:n,keyboard$:r}))))}catch(n){return e.hidden=!0,qe}}function ri(e,{index$:t,location$:r}){return Q([t,r.pipe(q(ve()),g(o=>!!o.searchParams.get("h")))]).pipe(m(([o,n])=>Yn(o.config)(n.searchParams.get("h"))),m(o=>{var s;let n=new Map,i=document.createNodeIterator(e,NodeFilter.SHOW_TEXT);for(let a=i.nextNode();a;a=i.nextNode())if((s=a.parentElement)!=null&&s.offsetHeight){let c=a.textContent,p=o(c);p.length>c.length&&n.set(a,p)}for(let[a,c]of n){let{childNodes:p}=E("span",null,c);a.replaceWith(...Array.from(p))}return{ref:e,nodes:n}}))}function Ya(e,{viewport$:t,main$:r}){let o=e.closest(".md-grid"),n=o.offsetTop-o.parentElement.offsetTop;return Q([r,t]).pipe(m(([{offset:i,height:s},{offset:{y:a}}])=>(s=s+Math.min(n,Math.max(0,a-i))-n,{height:s,locked:a>=i+n})),Y((i,s)=>i.height===s.height&&i.locked===s.locked))}function Qr(e,o){var n=o,{header$:t}=n,r=to(n,["header$"]);let i=P(".md-sidebar__scrollwrap",e),{y:s}=Ue(i);return H(()=>{let a=new v,c=a.pipe(ee(),oe(!0)),p=a.pipe(Me(0,de));return p.pipe(ae(t)).subscribe({next([{height:l},{height:f}]){i.style.height=`${l-2*s}px`,e.style.top=`${f}px`},complete(){i.style.height="",e.style.top=""}}),p.pipe(He()).subscribe(()=>{for(let l of R(".md-nav__link--active[href]",e)){if(!l.clientHeight)continue;let f=l.closest(".md-sidebar__scrollwrap");if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:h}=pe(f);f.scrollTo({top:u-h/2})}}}),fe(R("label[tabindex]",e)).pipe(re(l=>d(l,"click").pipe(Oe(ie),m(()=>l),U(c)))).subscribe(l=>{let f=P(`[id="${l.htmlFor}"]`);P(`[aria-labelledby="${l.id}"]`).setAttribute("aria-expanded",`${f.checked}`)}),Ya(e,r).pipe(y(l=>a.next(l)),_(()=>a.complete()),m(l=>F({ref:e},l)))})}function oi(e,t){if(typeof t!="undefined"){let r=`https://api.github.com/repos/${e}/${t}`;return Lt(De(`${r}/releases/latest`).pipe(he(()=>L),m(o=>({version:o.tag_name})),Qe({})),De(r).pipe(he(()=>L),m(o=>({stars:o.stargazers_count,forks:o.forks_count})),Qe({}))).pipe(m(([o,n])=>F(F({},o),n)))}else{let r=`https://api.github.com/users/${e}`;return De(r).pipe(m(o=>({repositories:o.public_repos})),Qe({}))}}function ni(e,t){let r=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return De(r).pipe(he(()=>L),m(({star_count:o,forks_count:n})=>({stars:o,forks:n})),Qe({}))}function ii(e){let t=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);if(t){let[,r,o]=t;return oi(r,o)}if(t=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i),t){let[,r,o]=t;return ni(r,o)}return L}var Ba;function Ga(e){return Ba||(Ba=H(()=>{let t=__md_get("__source",sessionStorage);if(t)return $(t);if(ne("consent").length){let o=__md_get("__consent");if(!(o&&o.github))return L}return ii(e.href).pipe(y(o=>__md_set("__source",o,sessionStorage)))}).pipe(he(()=>L),g(t=>Object.keys(t).length>0),m(t=>({facts:t})),B(1)))}function ai(e){let t=P(":scope > :last-child",e);return H(()=>{let r=new v;return r.subscribe(({facts:o})=>{t.appendChild(bn(o)),t.classList.add("md-source__repository--active")}),Ga(e).pipe(y(o=>r.next(o)),_(()=>r.complete()),m(o=>F({ref:e},o)))})}function Ja(e,{viewport$:t,header$:r}){return Ee(document.body).pipe(b(()=>pr(e,{header$:r,viewport$:t})),m(({offset:{y:o}})=>({hidden:o>=10})),X("hidden"))}function si(e,t){return H(()=>{let r=new v;return r.subscribe({next({hidden:o}){e.hidden=o},complete(){e.hidden=!1}}),(G("navigation.tabs.sticky")?$({hidden:!1}):Ja(e,t)).pipe(y(o=>r.next(o)),_(()=>r.complete()),m(o=>F({ref:e},o)))})}function Xa(e,{viewport$:t,header$:r}){let o=new Map,n=R(".md-nav__link",e);for(let a of n){let c=decodeURIComponent(a.hash.substring(1)),p=me(`[id="${c}"]`);typeof p!="undefined"&&o.set(a,p)}let i=r.pipe(X("height"),m(({height:a})=>{let c=Te("main"),p=P(":scope > :first-child",c);return a+.8*(p.offsetTop-c.offsetTop)}),le());return Ee(document.body).pipe(X("height"),b(a=>H(()=>{let c=[];return $([...o].reduce((p,[l,f])=>{for(;c.length&&o.get(c[c.length-1]).tagName>=f.tagName;)c.pop();let u=f.offsetTop;for(;!u&&f.parentElement;)f=f.parentElement,u=f.offsetTop;let h=f.offsetParent;for(;h;h=h.offsetParent)u+=h.offsetTop;return p.set([...c=[...c,l]].reverse(),u)},new Map))}).pipe(m(c=>new Map([...c].sort(([,p],[,l])=>p-l))),je(i),b(([c,p])=>t.pipe(Rr(([l,f],{offset:{y:u},size:h})=>{let w=u+h.height>=Math.floor(a.height);for(;f.length;){let[,A]=f[0];if(A-p=u&&!w)f=[l.pop(),...f];else break}return[l,f]},[[],[...c]]),Y((l,f)=>l[0]===f[0]&&l[1]===f[1])))))).pipe(m(([a,c])=>({prev:a.map(([p])=>p),next:c.map(([p])=>p)})),q({prev:[],next:[]}),Ke(2,1),m(([a,c])=>a.prev.length{let i=new v,s=i.pipe(ee(),oe(!0));if(i.subscribe(({prev:a,next:c})=>{for(let[p]of c)p.classList.remove("md-nav__link--passed"),p.classList.remove("md-nav__link--active");for(let[p,[l]]of a.entries())l.classList.add("md-nav__link--passed"),l.classList.toggle("md-nav__link--active",p===a.length-1)}),G("toc.follow")){let a=T(t.pipe(be(1),m(()=>{})),t.pipe(be(250),m(()=>"smooth")));i.pipe(g(({prev:c})=>c.length>0),je(o.pipe(Oe(ie))),ae(a)).subscribe(([[{prev:c}],p])=>{let[l]=c[c.length-1];if(l.offsetHeight){let f=sr(l);if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:h}=pe(f);f.scrollTo({top:u-h/2,behavior:p})}}})}return G("navigation.tracking")&&t.pipe(U(s),X("offset"),be(250),Le(1),U(n.pipe(Le(1))),at({delay:250}),ae(i)).subscribe(([,{prev:a}])=>{let c=ve(),p=a[a.length-1];if(p&&p.length){let[l]=p,{hash:f}=new URL(l.href);c.hash!==f&&(c.hash=f,history.replaceState({},"",`${c}`))}else c.hash="",history.replaceState({},"",`${c}`)}),Xa(e,{viewport$:t,header$:r}).pipe(y(a=>i.next(a)),_(()=>i.complete()),m(a=>F({ref:e},a)))})}function Za(e,{viewport$:t,main$:r,target$:o}){let n=t.pipe(m(({offset:{y:s}})=>s),Ke(2,1),m(([s,a])=>s>a&&a>0),Y()),i=r.pipe(m(({active:s})=>s));return Q([i,n]).pipe(m(([s,a])=>!(s&&a)),Y(),U(o.pipe(Le(1))),oe(!0),at({delay:250}),m(s=>({hidden:s})))}function pi(e,{viewport$:t,header$:r,main$:o,target$:n}){let i=new v,s=i.pipe(ee(),oe(!0));return i.subscribe({next({hidden:a}){e.hidden=a,a?(e.setAttribute("tabindex","-1"),e.blur()):e.removeAttribute("tabindex")},complete(){e.style.top="",e.hidden=!0,e.removeAttribute("tabindex")}}),r.pipe(U(s),X("height")).subscribe(({height:a})=>{e.style.top=`${a+16}px`}),d(e,"click").subscribe(a=>{a.preventDefault(),window.scrollTo({top:0})}),Za(e,{viewport$:t,main$:o,target$:n}).pipe(y(a=>i.next(a)),_(()=>i.complete()),m(a=>F({ref:e},a)))}function li({document$:e}){e.pipe(b(()=>R(".md-ellipsis")),re(t=>yt(t).pipe(U(e.pipe(Le(1))),g(r=>r),m(()=>t),ye(1))),g(t=>t.offsetWidth{let r=t.innerText,o=t.closest("a")||t;return o.title=r,Ge(o).pipe(U(e.pipe(Le(1))),_(()=>o.removeAttribute("title")))})).subscribe(),e.pipe(b(()=>R(".md-status")),re(t=>Ge(t))).subscribe()}function mi({document$:e,tablet$:t}){e.pipe(b(()=>R(".md-toggle--indeterminate")),y(r=>{r.indeterminate=!0,r.checked=!1}),re(r=>d(r,"change").pipe(Fr(()=>r.classList.contains("md-toggle--indeterminate")),m(()=>r))),ae(t)).subscribe(([r,o])=>{r.classList.remove("md-toggle--indeterminate"),o&&(r.checked=!1)})}function es(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}function fi({document$:e}){e.pipe(b(()=>R("[data-md-scrollfix]")),y(t=>t.removeAttribute("data-md-scrollfix")),g(es),re(t=>d(t,"touchstart").pipe(m(()=>t)))).subscribe(t=>{let r=t.scrollTop;r===0?t.scrollTop=1:r+t.offsetHeight===t.scrollHeight&&(t.scrollTop=r-1)})}function ui({viewport$:e,tablet$:t}){Q([We("search"),t]).pipe(m(([r,o])=>r&&!o),b(r=>$(r).pipe(Ye(r?400:100))),ae(e)).subscribe(([r,{offset:{y:o}}])=>{if(r)document.body.setAttribute("data-md-scrolllock",""),document.body.style.top=`-${o}px`;else{let n=-1*parseInt(document.body.style.top,10);document.body.removeAttribute("data-md-scrolllock"),document.body.style.top="",n&&window.scrollTo(0,n)}})}Object.entries||(Object.entries=function(e){let t=[];for(let r of Object.keys(e))t.push([r,e[r]]);return t});Object.values||(Object.values=function(e){let t=[];for(let r of Object.keys(e))t.push(e[r]);return t});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(e,t){typeof e=="object"?(this.scrollLeft=e.left,this.scrollTop=e.top):(this.scrollLeft=e,this.scrollTop=t)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...e){let t=this.parentNode;if(t){e.length===0&&t.removeChild(this);for(let r=e.length-1;r>=0;r--){let o=e[r];typeof o=="string"?o=document.createTextNode(o):o.parentNode&&o.parentNode.removeChild(o),r?t.insertBefore(this.previousSibling,o):t.replaceChild(o,this)}}}));function ts(){return location.protocol==="file:"?gt(`${new URL("search/search_index.js",Yr.base)}`).pipe(m(()=>__index),B(1)):De(new URL("search/search_index.json",Yr.base))}document.documentElement.classList.remove("no-js");document.documentElement.classList.add("js");var rt=No(),Rt=Jo(),wt=en(Rt),Br=Go(),_e=pn(),ur=At("(min-width: 960px)"),hi=At("(min-width: 1220px)"),bi=tn(),Yr=we(),vi=document.forms.namedItem("search")?ts():qe,Gr=new v;Wn({alert$:Gr});var Jr=new v;G("navigation.instant")&&zn({location$:Rt,viewport$:_e,progress$:Jr}).subscribe(rt);var di;((di=Yr.version)==null?void 0:di.provider)==="mike"&&Gn({document$:rt});T(Rt,wt).pipe(Ye(125)).subscribe(()=>{Be("drawer",!1),Be("search",!1)});Br.pipe(g(({mode:e})=>e==="global")).subscribe(e=>{switch(e.type){case"p":case",":let t=me("link[rel=prev]");typeof t!="undefined"&&st(t);break;case"n":case".":let r=me("link[rel=next]");typeof r!="undefined"&&st(r);break;case"Enter":let o=Re();o instanceof HTMLLabelElement&&o.click()}});li({document$:rt});mi({document$:rt,tablet$:ur});fi({document$:rt});ui({viewport$:_e,tablet$:ur});var tt=Rn(Te("header"),{viewport$:_e}),$t=rt.pipe(m(()=>Te("main")),b(e=>Fn(e,{viewport$:_e,header$:tt})),B(1)),rs=T(...ne("consent").map(e=>fn(e,{target$:wt})),...ne("dialog").map(e=>$n(e,{alert$:Gr})),...ne("header").map(e=>Pn(e,{viewport$:_e,header$:tt,main$:$t})),...ne("palette").map(e=>jn(e)),...ne("progress").map(e=>Un(e,{progress$:Jr})),...ne("search").map(e=>ti(e,{index$:vi,keyboard$:Br})),...ne("source").map(e=>ai(e))),os=H(()=>T(...ne("announce").map(e=>mn(e)),...ne("content").map(e=>Hn(e,{viewport$:_e,target$:wt,print$:bi})),...ne("content").map(e=>G("search.highlight")?ri(e,{index$:vi,location$:Rt}):L),...ne("header-title").map(e=>In(e,{viewport$:_e,header$:tt})),...ne("sidebar").map(e=>e.getAttribute("data-md-type")==="navigation"?Ur(hi,()=>Qr(e,{viewport$:_e,header$:tt,main$:$t})):Ur(ur,()=>Qr(e,{viewport$:_e,header$:tt,main$:$t}))),...ne("tabs").map(e=>si(e,{viewport$:_e,header$:tt})),...ne("toc").map(e=>ci(e,{viewport$:_e,header$:tt,main$:$t,target$:wt})),...ne("top").map(e=>pi(e,{viewport$:_e,header$:tt,main$:$t,target$:wt})))),gi=rt.pipe(b(()=>os),$e(rs),B(1));gi.subscribe();window.document$=rt;window.location$=Rt;window.target$=wt;window.keyboard$=Br;window.viewport$=_e;window.tablet$=ur;window.screen$=hi;window.print$=bi;window.alert$=Gr;window.progress$=Jr;window.component$=gi;})(); +//# sourceMappingURL=bundle.c8d2eff1.min.js.map + diff --git a/assets/javascripts/bundle.c8d2eff1.min.js.map b/assets/javascripts/bundle.c8d2eff1.min.js.map new file mode 100644 index 0000000..fc522db --- /dev/null +++ b/assets/javascripts/bundle.c8d2eff1.min.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["node_modules/focus-visible/dist/focus-visible.js", "node_modules/clipboard/dist/clipboard.js", "node_modules/escape-html/index.js", "src/templates/assets/javascripts/bundle.ts", "node_modules/rxjs/node_modules/tslib/tslib.es6.js", "node_modules/rxjs/src/internal/util/isFunction.ts", "node_modules/rxjs/src/internal/util/createErrorClass.ts", "node_modules/rxjs/src/internal/util/UnsubscriptionError.ts", "node_modules/rxjs/src/internal/util/arrRemove.ts", "node_modules/rxjs/src/internal/Subscription.ts", "node_modules/rxjs/src/internal/config.ts", "node_modules/rxjs/src/internal/scheduler/timeoutProvider.ts", "node_modules/rxjs/src/internal/util/reportUnhandledError.ts", "node_modules/rxjs/src/internal/util/noop.ts", "node_modules/rxjs/src/internal/NotificationFactories.ts", "node_modules/rxjs/src/internal/util/errorContext.ts", "node_modules/rxjs/src/internal/Subscriber.ts", "node_modules/rxjs/src/internal/symbol/observable.ts", "node_modules/rxjs/src/internal/util/identity.ts", "node_modules/rxjs/src/internal/util/pipe.ts", "node_modules/rxjs/src/internal/Observable.ts", "node_modules/rxjs/src/internal/util/lift.ts", "node_modules/rxjs/src/internal/operators/OperatorSubscriber.ts", "node_modules/rxjs/src/internal/scheduler/animationFrameProvider.ts", "node_modules/rxjs/src/internal/util/ObjectUnsubscribedError.ts", "node_modules/rxjs/src/internal/Subject.ts", "node_modules/rxjs/src/internal/scheduler/dateTimestampProvider.ts", "node_modules/rxjs/src/internal/ReplaySubject.ts", "node_modules/rxjs/src/internal/scheduler/Action.ts", "node_modules/rxjs/src/internal/scheduler/intervalProvider.ts", "node_modules/rxjs/src/internal/scheduler/AsyncAction.ts", "node_modules/rxjs/src/internal/Scheduler.ts", "node_modules/rxjs/src/internal/scheduler/AsyncScheduler.ts", "node_modules/rxjs/src/internal/scheduler/async.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameAction.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameScheduler.ts", "node_modules/rxjs/src/internal/scheduler/animationFrame.ts", "node_modules/rxjs/src/internal/observable/empty.ts", "node_modules/rxjs/src/internal/util/isScheduler.ts", "node_modules/rxjs/src/internal/util/args.ts", "node_modules/rxjs/src/internal/util/isArrayLike.ts", "node_modules/rxjs/src/internal/util/isPromise.ts", "node_modules/rxjs/src/internal/util/isInteropObservable.ts", "node_modules/rxjs/src/internal/util/isAsyncIterable.ts", "node_modules/rxjs/src/internal/util/throwUnobservableError.ts", "node_modules/rxjs/src/internal/symbol/iterator.ts", "node_modules/rxjs/src/internal/util/isIterable.ts", "node_modules/rxjs/src/internal/util/isReadableStreamLike.ts", "node_modules/rxjs/src/internal/observable/innerFrom.ts", "node_modules/rxjs/src/internal/util/executeSchedule.ts", "node_modules/rxjs/src/internal/operators/observeOn.ts", "node_modules/rxjs/src/internal/operators/subscribeOn.ts", "node_modules/rxjs/src/internal/scheduled/scheduleObservable.ts", "node_modules/rxjs/src/internal/scheduled/schedulePromise.ts", "node_modules/rxjs/src/internal/scheduled/scheduleArray.ts", "node_modules/rxjs/src/internal/scheduled/scheduleIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleAsyncIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleReadableStreamLike.ts", "node_modules/rxjs/src/internal/scheduled/scheduled.ts", "node_modules/rxjs/src/internal/observable/from.ts", "node_modules/rxjs/src/internal/observable/of.ts", "node_modules/rxjs/src/internal/observable/throwError.ts", "node_modules/rxjs/src/internal/util/EmptyError.ts", "node_modules/rxjs/src/internal/util/isDate.ts", "node_modules/rxjs/src/internal/operators/map.ts", "node_modules/rxjs/src/internal/util/mapOneOrManyArgs.ts", "node_modules/rxjs/src/internal/util/argsArgArrayOrObject.ts", "node_modules/rxjs/src/internal/util/createObject.ts", "node_modules/rxjs/src/internal/observable/combineLatest.ts", "node_modules/rxjs/src/internal/operators/mergeInternals.ts", "node_modules/rxjs/src/internal/operators/mergeMap.ts", "node_modules/rxjs/src/internal/operators/mergeAll.ts", "node_modules/rxjs/src/internal/operators/concatAll.ts", "node_modules/rxjs/src/internal/observable/concat.ts", "node_modules/rxjs/src/internal/observable/defer.ts", "node_modules/rxjs/src/internal/observable/fromEvent.ts", "node_modules/rxjs/src/internal/observable/fromEventPattern.ts", "node_modules/rxjs/src/internal/observable/timer.ts", "node_modules/rxjs/src/internal/observable/merge.ts", "node_modules/rxjs/src/internal/observable/never.ts", "node_modules/rxjs/src/internal/util/argsOrArgArray.ts", "node_modules/rxjs/src/internal/operators/filter.ts", "node_modules/rxjs/src/internal/observable/zip.ts", "node_modules/rxjs/src/internal/operators/audit.ts", "node_modules/rxjs/src/internal/operators/auditTime.ts", "node_modules/rxjs/src/internal/operators/bufferCount.ts", "node_modules/rxjs/src/internal/operators/catchError.ts", "node_modules/rxjs/src/internal/operators/scanInternals.ts", "node_modules/rxjs/src/internal/operators/combineLatest.ts", "node_modules/rxjs/src/internal/operators/combineLatestWith.ts", "node_modules/rxjs/src/internal/operators/debounceTime.ts", "node_modules/rxjs/src/internal/operators/defaultIfEmpty.ts", "node_modules/rxjs/src/internal/operators/take.ts", "node_modules/rxjs/src/internal/operators/ignoreElements.ts", "node_modules/rxjs/src/internal/operators/mapTo.ts", "node_modules/rxjs/src/internal/operators/delayWhen.ts", "node_modules/rxjs/src/internal/operators/delay.ts", "node_modules/rxjs/src/internal/operators/distinctUntilChanged.ts", "node_modules/rxjs/src/internal/operators/distinctUntilKeyChanged.ts", "node_modules/rxjs/src/internal/operators/throwIfEmpty.ts", "node_modules/rxjs/src/internal/operators/endWith.ts", "node_modules/rxjs/src/internal/operators/finalize.ts", "node_modules/rxjs/src/internal/operators/first.ts", "node_modules/rxjs/src/internal/operators/takeLast.ts", "node_modules/rxjs/src/internal/operators/merge.ts", "node_modules/rxjs/src/internal/operators/mergeWith.ts", "node_modules/rxjs/src/internal/operators/repeat.ts", "node_modules/rxjs/src/internal/operators/scan.ts", "node_modules/rxjs/src/internal/operators/share.ts", "node_modules/rxjs/src/internal/operators/shareReplay.ts", "node_modules/rxjs/src/internal/operators/skip.ts", "node_modules/rxjs/src/internal/operators/skipUntil.ts", "node_modules/rxjs/src/internal/operators/startWith.ts", "node_modules/rxjs/src/internal/operators/switchMap.ts", "node_modules/rxjs/src/internal/operators/takeUntil.ts", "node_modules/rxjs/src/internal/operators/takeWhile.ts", "node_modules/rxjs/src/internal/operators/tap.ts", "node_modules/rxjs/src/internal/operators/throttle.ts", "node_modules/rxjs/src/internal/operators/throttleTime.ts", "node_modules/rxjs/src/internal/operators/withLatestFrom.ts", "node_modules/rxjs/src/internal/operators/zip.ts", "node_modules/rxjs/src/internal/operators/zipWith.ts", "src/templates/assets/javascripts/browser/document/index.ts", "src/templates/assets/javascripts/browser/element/_/index.ts", "src/templates/assets/javascripts/browser/element/focus/index.ts", "src/templates/assets/javascripts/browser/element/hover/index.ts", "src/templates/assets/javascripts/browser/element/offset/_/index.ts", "src/templates/assets/javascripts/browser/element/offset/content/index.ts", "src/templates/assets/javascripts/utilities/h/index.ts", "src/templates/assets/javascripts/utilities/round/index.ts", "src/templates/assets/javascripts/browser/script/index.ts", "src/templates/assets/javascripts/browser/element/size/_/index.ts", "src/templates/assets/javascripts/browser/element/size/content/index.ts", "src/templates/assets/javascripts/browser/element/visibility/index.ts", "src/templates/assets/javascripts/browser/toggle/index.ts", "src/templates/assets/javascripts/browser/keyboard/index.ts", "src/templates/assets/javascripts/browser/location/_/index.ts", "src/templates/assets/javascripts/browser/location/hash/index.ts", "src/templates/assets/javascripts/browser/media/index.ts", "src/templates/assets/javascripts/browser/request/index.ts", "src/templates/assets/javascripts/browser/viewport/offset/index.ts", "src/templates/assets/javascripts/browser/viewport/size/index.ts", "src/templates/assets/javascripts/browser/viewport/_/index.ts", "src/templates/assets/javascripts/browser/viewport/at/index.ts", "src/templates/assets/javascripts/browser/worker/index.ts", "src/templates/assets/javascripts/_/index.ts", "src/templates/assets/javascripts/components/_/index.ts", "src/templates/assets/javascripts/components/announce/index.ts", "src/templates/assets/javascripts/components/consent/index.ts", "src/templates/assets/javascripts/templates/tooltip/index.tsx", "src/templates/assets/javascripts/templates/annotation/index.tsx", "src/templates/assets/javascripts/templates/clipboard/index.tsx", "src/templates/assets/javascripts/templates/search/index.tsx", "src/templates/assets/javascripts/templates/source/index.tsx", "src/templates/assets/javascripts/templates/tabbed/index.tsx", "src/templates/assets/javascripts/templates/table/index.tsx", "src/templates/assets/javascripts/templates/version/index.tsx", "src/templates/assets/javascripts/components/tooltip/index.ts", "src/templates/assets/javascripts/components/content/annotation/_/index.ts", "src/templates/assets/javascripts/components/content/annotation/list/index.ts", "src/templates/assets/javascripts/components/content/annotation/block/index.ts", "src/templates/assets/javascripts/components/content/code/_/index.ts", "src/templates/assets/javascripts/components/content/details/index.ts", "src/templates/assets/javascripts/components/content/mermaid/index.css", "src/templates/assets/javascripts/components/content/mermaid/index.ts", "src/templates/assets/javascripts/components/content/table/index.ts", "src/templates/assets/javascripts/components/content/tabs/index.ts", "src/templates/assets/javascripts/components/content/_/index.ts", "src/templates/assets/javascripts/components/dialog/index.ts", "src/templates/assets/javascripts/components/header/_/index.ts", "src/templates/assets/javascripts/components/header/title/index.ts", "src/templates/assets/javascripts/components/main/index.ts", "src/templates/assets/javascripts/components/palette/index.ts", "src/templates/assets/javascripts/components/progress/index.ts", "src/templates/assets/javascripts/integrations/clipboard/index.ts", "src/templates/assets/javascripts/integrations/sitemap/index.ts", "src/templates/assets/javascripts/integrations/instant/index.ts", "src/templates/assets/javascripts/integrations/search/highlighter/index.ts", "src/templates/assets/javascripts/integrations/search/worker/message/index.ts", "src/templates/assets/javascripts/integrations/search/worker/_/index.ts", "src/templates/assets/javascripts/integrations/version/index.ts", "src/templates/assets/javascripts/components/search/query/index.ts", "src/templates/assets/javascripts/components/search/result/index.ts", "src/templates/assets/javascripts/components/search/share/index.ts", "src/templates/assets/javascripts/components/search/suggest/index.ts", "src/templates/assets/javascripts/components/search/_/index.ts", "src/templates/assets/javascripts/components/search/highlight/index.ts", "src/templates/assets/javascripts/components/sidebar/index.ts", "src/templates/assets/javascripts/components/source/facts/github/index.ts", "src/templates/assets/javascripts/components/source/facts/gitlab/index.ts", "src/templates/assets/javascripts/components/source/facts/_/index.ts", "src/templates/assets/javascripts/components/source/_/index.ts", "src/templates/assets/javascripts/components/tabs/index.ts", "src/templates/assets/javascripts/components/toc/index.ts", "src/templates/assets/javascripts/components/top/index.ts", "src/templates/assets/javascripts/patches/ellipsis/index.ts", "src/templates/assets/javascripts/patches/indeterminate/index.ts", "src/templates/assets/javascripts/patches/scrollfix/index.ts", "src/templates/assets/javascripts/patches/scrolllock/index.ts", "src/templates/assets/javascripts/polyfills/index.ts"], + "sourcesContent": ["(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (factory());\n}(this, (function () { 'use strict';\n\n /**\n * Applies the :focus-visible polyfill at the given scope.\n * A scope in this case is either the top-level Document or a Shadow Root.\n *\n * @param {(Document|ShadowRoot)} scope\n * @see https://github.com/WICG/focus-visible\n */\n function applyFocusVisiblePolyfill(scope) {\n var hadKeyboardEvent = true;\n var hadFocusVisibleRecently = false;\n var hadFocusVisibleRecentlyTimeout = null;\n\n var inputTypesAllowlist = {\n text: true,\n search: true,\n url: true,\n tel: true,\n email: true,\n password: true,\n number: true,\n date: true,\n month: true,\n week: true,\n time: true,\n datetime: true,\n 'datetime-local': true\n };\n\n /**\n * Helper function for legacy browsers and iframes which sometimes focus\n * elements like document, body, and non-interactive SVG.\n * @param {Element} el\n */\n function isValidFocusTarget(el) {\n if (\n el &&\n el !== document &&\n el.nodeName !== 'HTML' &&\n el.nodeName !== 'BODY' &&\n 'classList' in el &&\n 'contains' in el.classList\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * Computes whether the given element should automatically trigger the\n * `focus-visible` class being added, i.e. whether it should always match\n * `:focus-visible` when focused.\n * @param {Element} el\n * @return {boolean}\n */\n function focusTriggersKeyboardModality(el) {\n var type = el.type;\n var tagName = el.tagName;\n\n if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) {\n return true;\n }\n\n if (tagName === 'TEXTAREA' && !el.readOnly) {\n return true;\n }\n\n if (el.isContentEditable) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Add the `focus-visible` class to the given element if it was not added by\n * the author.\n * @param {Element} el\n */\n function addFocusVisibleClass(el) {\n if (el.classList.contains('focus-visible')) {\n return;\n }\n el.classList.add('focus-visible');\n el.setAttribute('data-focus-visible-added', '');\n }\n\n /**\n * Remove the `focus-visible` class from the given element if it was not\n * originally added by the author.\n * @param {Element} el\n */\n function removeFocusVisibleClass(el) {\n if (!el.hasAttribute('data-focus-visible-added')) {\n return;\n }\n el.classList.remove('focus-visible');\n el.removeAttribute('data-focus-visible-added');\n }\n\n /**\n * If the most recent user interaction was via the keyboard;\n * and the key press did not include a meta, alt/option, or control key;\n * then the modality is keyboard. Otherwise, the modality is not keyboard.\n * Apply `focus-visible` to any current active element and keep track\n * of our keyboard modality state with `hadKeyboardEvent`.\n * @param {KeyboardEvent} e\n */\n function onKeyDown(e) {\n if (e.metaKey || e.altKey || e.ctrlKey) {\n return;\n }\n\n if (isValidFocusTarget(scope.activeElement)) {\n addFocusVisibleClass(scope.activeElement);\n }\n\n hadKeyboardEvent = true;\n }\n\n /**\n * If at any point a user clicks with a pointing device, ensure that we change\n * the modality away from keyboard.\n * This avoids the situation where a user presses a key on an already focused\n * element, and then clicks on a different element, focusing it with a\n * pointing device, while we still think we're in keyboard modality.\n * @param {Event} e\n */\n function onPointerDown(e) {\n hadKeyboardEvent = false;\n }\n\n /**\n * On `focus`, add the `focus-visible` class to the target if:\n * - the target received focus as a result of keyboard navigation, or\n * - the event target is an element that will likely require interaction\n * via the keyboard (e.g. a text box)\n * @param {Event} e\n */\n function onFocus(e) {\n // Prevent IE from focusing the document or HTML element.\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {\n addFocusVisibleClass(e.target);\n }\n }\n\n /**\n * On `blur`, remove the `focus-visible` class from the target.\n * @param {Event} e\n */\n function onBlur(e) {\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (\n e.target.classList.contains('focus-visible') ||\n e.target.hasAttribute('data-focus-visible-added')\n ) {\n // To detect a tab/window switch, we look for a blur event followed\n // rapidly by a visibility change.\n // If we don't see a visibility change within 100ms, it's probably a\n // regular focus change.\n hadFocusVisibleRecently = true;\n window.clearTimeout(hadFocusVisibleRecentlyTimeout);\n hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {\n hadFocusVisibleRecently = false;\n }, 100);\n removeFocusVisibleClass(e.target);\n }\n }\n\n /**\n * If the user changes tabs, keep track of whether or not the previously\n * focused element had .focus-visible.\n * @param {Event} e\n */\n function onVisibilityChange(e) {\n if (document.visibilityState === 'hidden') {\n // If the tab becomes active again, the browser will handle calling focus\n // on the element (Safari actually calls it twice).\n // If this tab change caused a blur on an element with focus-visible,\n // re-apply the class when the user switches back to the tab.\n if (hadFocusVisibleRecently) {\n hadKeyboardEvent = true;\n }\n addInitialPointerMoveListeners();\n }\n }\n\n /**\n * Add a group of listeners to detect usage of any pointing devices.\n * These listeners will be added when the polyfill first loads, and anytime\n * the window is blurred, so that they are active when the window regains\n * focus.\n */\n function addInitialPointerMoveListeners() {\n document.addEventListener('mousemove', onInitialPointerMove);\n document.addEventListener('mousedown', onInitialPointerMove);\n document.addEventListener('mouseup', onInitialPointerMove);\n document.addEventListener('pointermove', onInitialPointerMove);\n document.addEventListener('pointerdown', onInitialPointerMove);\n document.addEventListener('pointerup', onInitialPointerMove);\n document.addEventListener('touchmove', onInitialPointerMove);\n document.addEventListener('touchstart', onInitialPointerMove);\n document.addEventListener('touchend', onInitialPointerMove);\n }\n\n function removeInitialPointerMoveListeners() {\n document.removeEventListener('mousemove', onInitialPointerMove);\n document.removeEventListener('mousedown', onInitialPointerMove);\n document.removeEventListener('mouseup', onInitialPointerMove);\n document.removeEventListener('pointermove', onInitialPointerMove);\n document.removeEventListener('pointerdown', onInitialPointerMove);\n document.removeEventListener('pointerup', onInitialPointerMove);\n document.removeEventListener('touchmove', onInitialPointerMove);\n document.removeEventListener('touchstart', onInitialPointerMove);\n document.removeEventListener('touchend', onInitialPointerMove);\n }\n\n /**\n * When the polfyill first loads, assume the user is in keyboard modality.\n * If any event is received from a pointing device (e.g. mouse, pointer,\n * touch), turn off keyboard modality.\n * This accounts for situations where focus enters the page from the URL bar.\n * @param {Event} e\n */\n function onInitialPointerMove(e) {\n // Work around a Safari quirk that fires a mousemove on whenever the\n // window blurs, even if you're tabbing out of the page. \u00AF\\_(\u30C4)_/\u00AF\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n document.documentElement.setAttribute('data-js-focus-visible', '');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n", "/*!\n * clipboard.js v2.0.11\n * https://clipboardjs.com/\n *\n * Licensed MIT \u00A9 Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function() { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 686:\n/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"default\": function() { return /* binding */ clipboard; }\n});\n\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(279);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(370);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(817);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n;// CONCATENATED MODULE: ./src/common/command.js\n/**\n * Executes a given operation type.\n * @param {String} type\n * @return {Boolean}\n */\nfunction command(type) {\n try {\n return document.execCommand(type);\n } catch (err) {\n return false;\n }\n}\n;// CONCATENATED MODULE: ./src/actions/cut.js\n\n\n/**\n * Cut action wrapper.\n * @param {String|HTMLElement} target\n * @return {String}\n */\n\nvar ClipboardActionCut = function ClipboardActionCut(target) {\n var selectedText = select_default()(target);\n command('cut');\n return selectedText;\n};\n\n/* harmony default export */ var actions_cut = (ClipboardActionCut);\n;// CONCATENATED MODULE: ./src/common/create-fake-element.js\n/**\n * Creates a fake textarea element with a value.\n * @param {String} value\n * @return {HTMLElement}\n */\nfunction createFakeElement(value) {\n var isRTL = document.documentElement.getAttribute('dir') === 'rtl';\n var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS\n\n fakeElement.style.fontSize = '12pt'; // Reset box model\n\n fakeElement.style.border = '0';\n fakeElement.style.padding = '0';\n fakeElement.style.margin = '0'; // Move element out of screen horizontally\n\n fakeElement.style.position = 'absolute';\n fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically\n\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n fakeElement.style.top = \"\".concat(yPosition, \"px\");\n fakeElement.setAttribute('readonly', '');\n fakeElement.value = value;\n return fakeElement;\n}\n;// CONCATENATED MODULE: ./src/actions/copy.js\n\n\n\n/**\n * Create fake copy action wrapper using a fake element.\n * @param {String} target\n * @param {Object} options\n * @return {String}\n */\n\nvar fakeCopyAction = function fakeCopyAction(value, options) {\n var fakeElement = createFakeElement(value);\n options.container.appendChild(fakeElement);\n var selectedText = select_default()(fakeElement);\n command('copy');\n fakeElement.remove();\n return selectedText;\n};\n/**\n * Copy action wrapper.\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @return {String}\n */\n\n\nvar ClipboardActionCopy = function ClipboardActionCopy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n var selectedText = '';\n\n if (typeof target === 'string') {\n selectedText = fakeCopyAction(target, options);\n } else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) {\n // If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange\n selectedText = fakeCopyAction(target.value, options);\n } else {\n selectedText = select_default()(target);\n command('copy');\n }\n\n return selectedText;\n};\n\n/* harmony default export */ var actions_copy = (ClipboardActionCopy);\n;// CONCATENATED MODULE: ./src/actions/default.js\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n\n\n/**\n * Inner function which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n * @param {Object} options\n */\n\nvar ClipboardActionDefault = function ClipboardActionDefault() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Defines base properties passed from constructor.\n var _options$action = options.action,\n action = _options$action === void 0 ? 'copy' : _options$action,\n container = options.container,\n target = options.target,\n text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'.\n\n if (action !== 'copy' && action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n } // Sets the `target` property using an element that will be have its content copied.\n\n\n if (target !== undefined) {\n if (target && _typeof(target) === 'object' && target.nodeType === 1) {\n if (action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n } // Define selection strategy based on `text` property.\n\n\n if (text) {\n return actions_copy(text, {\n container: container\n });\n } // Defines which selection strategy based on `target` property.\n\n\n if (target) {\n return action === 'cut' ? actions_cut(target) : actions_copy(target, {\n container: container\n });\n }\n};\n\n/* harmony default export */ var actions_default = (ClipboardActionDefault);\n;// CONCATENATED MODULE: ./src/clipboard.js\nfunction clipboard_typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return clipboard_typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\nfunction getAttributeValue(suffix, element) {\n var attribute = \"data-clipboard-\".concat(suffix);\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\n\nvar Clipboard = /*#__PURE__*/function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n var _super = _createSuper(Clipboard);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n var _this;\n\n _classCallCheck(this, Clipboard);\n\n _this = _super.call(this);\n\n _this.resolveOptions(options);\n\n _this.listenClick(trigger);\n\n return _this;\n }\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n _createClass(Clipboard, [{\n key: \"resolveOptions\",\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: \"listenClick\",\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: \"onClick\",\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n var action = this.action(trigger) || 'copy';\n var text = actions_default({\n action: action,\n container: this.container,\n target: this.target(trigger),\n text: this.text(trigger)\n }); // Fires an event based on the copy operation result.\n\n this.emit(text ? 'success' : 'error', {\n action: action,\n text: text,\n trigger: trigger,\n clearSelection: function clearSelection() {\n if (trigger) {\n trigger.focus();\n }\n\n window.getSelection().removeAllRanges();\n }\n });\n }\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultAction\",\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultTarget\",\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n /**\n * Allow fire programmatically a copy action\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @returns Text copied.\n */\n\n }, {\n key: \"defaultText\",\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: \"destroy\",\n value: function destroy() {\n this.listener.destroy();\n }\n }], [{\n key: \"copy\",\n value: function copy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n return actions_copy(target, options);\n }\n /**\n * Allow fire programmatically a cut action\n * @param {String|HTMLElement} target\n * @returns Text cutted.\n */\n\n }, {\n key: \"cut\",\n value: function cut(target) {\n return actions_cut(target);\n }\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: \"isSupported\",\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n return support;\n }\n }]);\n\n return Clipboard;\n}((tiny_emitter_default()));\n\n/* harmony default export */ var clipboard = (Clipboard);\n\n/***/ }),\n\n/***/ 828:\n/***/ (function(module) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n\n/***/ 438:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar closest = __webpack_require__(828);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n\n/***/ 879:\n/***/ (function(__unused_webpack_module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n\n/***/ 370:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar is = __webpack_require__(879);\nvar delegate = __webpack_require__(438);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n\n/***/ 817:\n/***/ (function(module) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n\n/***/ 279:\n/***/ (function(module) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(__webpack_module_cache__[moduleId]) {\n/******/ \t\t\treturn __webpack_module_cache__[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\t// no module.id needed\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/compat get default export */\n/******/ \t!function() {\n/******/ \t\t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t\t__webpack_require__.n = function(module) {\n/******/ \t\t\tvar getter = module && module.__esModule ?\n/******/ \t\t\t\tfunction() { return module['default']; } :\n/******/ \t\t\t\tfunction() { return module; };\n/******/ \t\t\t__webpack_require__.d(getter, { a: getter });\n/******/ \t\t\treturn getter;\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/define property getters */\n/******/ \t!function() {\n/******/ \t\t// define getter functions for harmony exports\n/******/ \t\t__webpack_require__.d = function(exports, definition) {\n/******/ \t\t\tfor(var key in definition) {\n/******/ \t\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t\t}\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/hasOwnProperty shorthand */\n/******/ \t!function() {\n/******/ \t\t__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }\n/******/ \t}();\n/******/ \t\n/************************************************************************/\n/******/ \t// module exports must be returned from runtime so entry inlining is disabled\n/******/ \t// startup\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(686);\n/******/ })()\n.default;\n});", "/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n", "/*\n * Copyright (c) 2016-2024 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"focus-visible\"\n\nimport {\n EMPTY,\n NEVER,\n Observable,\n Subject,\n defer,\n delay,\n filter,\n map,\n merge,\n mergeWith,\n shareReplay,\n switchMap\n} from \"rxjs\"\n\nimport { configuration, feature } from \"./_\"\nimport {\n at,\n getActiveElement,\n getOptionalElement,\n requestJSON,\n setLocation,\n setToggle,\n watchDocument,\n watchKeyboard,\n watchLocation,\n watchLocationTarget,\n watchMedia,\n watchPrint,\n watchScript,\n watchViewport\n} from \"./browser\"\nimport {\n getComponentElement,\n getComponentElements,\n mountAnnounce,\n mountBackToTop,\n mountConsent,\n mountContent,\n mountDialog,\n mountHeader,\n mountHeaderTitle,\n mountPalette,\n mountProgress,\n mountSearch,\n mountSearchHiglight,\n mountSidebar,\n mountSource,\n mountTableOfContents,\n mountTabs,\n watchHeader,\n watchMain\n} from \"./components\"\nimport {\n SearchIndex,\n setupClipboardJS,\n setupInstantNavigation,\n setupVersionSelector\n} from \"./integrations\"\nimport {\n patchEllipsis,\n patchIndeterminate,\n patchScrollfix,\n patchScrolllock\n} from \"./patches\"\nimport \"./polyfills\"\n\n/* ----------------------------------------------------------------------------\n * Functions - @todo refactor\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch search index\n *\n * @returns Search index observable\n */\nfunction fetchSearchIndex(): Observable {\n if (location.protocol === \"file:\") {\n return watchScript(\n `${new URL(\"search/search_index.js\", config.base)}`\n )\n .pipe(\n // @ts-ignore - @todo fix typings\n map(() => __index),\n shareReplay(1)\n )\n } else {\n return requestJSON(\n new URL(\"search/search_index.json\", config.base)\n )\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Application\n * ------------------------------------------------------------------------- */\n\n/* Yay, JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Set up navigation observables and subjects */\nconst document$ = watchDocument()\nconst location$ = watchLocation()\nconst target$ = watchLocationTarget(location$)\nconst keyboard$ = watchKeyboard()\n\n/* Set up media observables */\nconst viewport$ = watchViewport()\nconst tablet$ = watchMedia(\"(min-width: 960px)\")\nconst screen$ = watchMedia(\"(min-width: 1220px)\")\nconst print$ = watchPrint()\n\n/* Retrieve search index, if search is enabled */\nconst config = configuration()\nconst index$ = document.forms.namedItem(\"search\")\n ? fetchSearchIndex()\n : NEVER\n\n/* Set up Clipboard.js integration */\nconst alert$ = new Subject()\nsetupClipboardJS({ alert$ })\n\n/* Set up progress indicator */\nconst progress$ = new Subject()\n\n/* Set up instant navigation, if enabled */\nif (feature(\"navigation.instant\"))\n setupInstantNavigation({ location$, viewport$, progress$ })\n .subscribe(document$)\n\n/* Set up version selector */\nif (config.version?.provider === \"mike\")\n setupVersionSelector({ document$ })\n\n/* Always close drawer and search on navigation */\nmerge(location$, target$)\n .pipe(\n delay(125)\n )\n .subscribe(() => {\n setToggle(\"drawer\", false)\n setToggle(\"search\", false)\n })\n\n/* Set up global keyboard handlers */\nkeyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\")\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Go to previous page */\n case \"p\":\n case \",\":\n const prev = getOptionalElement(\"link[rel=prev]\")\n if (typeof prev !== \"undefined\")\n setLocation(prev)\n break\n\n /* Go to next page */\n case \"n\":\n case \".\":\n const next = getOptionalElement(\"link[rel=next]\")\n if (typeof next !== \"undefined\")\n setLocation(next)\n break\n\n /* Expand navigation, see https://bit.ly/3ZjG5io */\n case \"Enter\":\n const active = getActiveElement()\n if (active instanceof HTMLLabelElement)\n active.click()\n }\n })\n\n/* Set up patches */\npatchEllipsis({ document$ })\npatchIndeterminate({ document$, tablet$ })\npatchScrollfix({ document$ })\npatchScrolllock({ viewport$, tablet$ })\n\n/* Set up header and main area observable */\nconst header$ = watchHeader(getComponentElement(\"header\"), { viewport$ })\nconst main$ = document$\n .pipe(\n map(() => getComponentElement(\"main\")),\n switchMap(el => watchMain(el, { viewport$, header$ })),\n shareReplay(1)\n )\n\n/* Set up control component observables */\nconst control$ = merge(\n\n /* Consent */\n ...getComponentElements(\"consent\")\n .map(el => mountConsent(el, { target$ })),\n\n /* Dialog */\n ...getComponentElements(\"dialog\")\n .map(el => mountDialog(el, { alert$ })),\n\n /* Header */\n ...getComponentElements(\"header\")\n .map(el => mountHeader(el, { viewport$, header$, main$ })),\n\n /* Color palette */\n ...getComponentElements(\"palette\")\n .map(el => mountPalette(el)),\n\n /* Progress bar */\n ...getComponentElements(\"progress\")\n .map(el => mountProgress(el, { progress$ })),\n\n /* Search */\n ...getComponentElements(\"search\")\n .map(el => mountSearch(el, { index$, keyboard$ })),\n\n /* Repository information */\n ...getComponentElements(\"source\")\n .map(el => mountSource(el))\n)\n\n/* Set up content component observables */\nconst content$ = defer(() => merge(\n\n /* Announcement bar */\n ...getComponentElements(\"announce\")\n .map(el => mountAnnounce(el)),\n\n /* Content */\n ...getComponentElements(\"content\")\n .map(el => mountContent(el, { viewport$, target$, print$ })),\n\n /* Search highlighting */\n ...getComponentElements(\"content\")\n .map(el => feature(\"search.highlight\")\n ? mountSearchHiglight(el, { index$, location$ })\n : EMPTY\n ),\n\n /* Header title */\n ...getComponentElements(\"header-title\")\n .map(el => mountHeaderTitle(el, { viewport$, header$ })),\n\n /* Sidebar */\n ...getComponentElements(\"sidebar\")\n .map(el => el.getAttribute(\"data-md-type\") === \"navigation\"\n ? at(screen$, () => mountSidebar(el, { viewport$, header$, main$ }))\n : at(tablet$, () => mountSidebar(el, { viewport$, header$, main$ }))\n ),\n\n /* Navigation tabs */\n ...getComponentElements(\"tabs\")\n .map(el => mountTabs(el, { viewport$, header$ })),\n\n /* Table of contents */\n ...getComponentElements(\"toc\")\n .map(el => mountTableOfContents(el, {\n viewport$, header$, main$, target$\n })),\n\n /* Back-to-top button */\n ...getComponentElements(\"top\")\n .map(el => mountBackToTop(el, { viewport$, header$, main$, target$ }))\n))\n\n/* Set up component observables */\nconst component$ = document$\n .pipe(\n switchMap(() => content$),\n mergeWith(control$),\n shareReplay(1)\n )\n\n/* Subscribe to all components */\ncomponent$.subscribe()\n\n/* ----------------------------------------------------------------------------\n * Exports\n * ------------------------------------------------------------------------- */\n\nwindow.document$ = document$ /* Document observable */\nwindow.location$ = location$ /* Location subject */\nwindow.target$ = target$ /* Location target observable */\nwindow.keyboard$ = keyboard$ /* Keyboard observable */\nwindow.viewport$ = viewport$ /* Viewport observable */\nwindow.tablet$ = tablet$ /* Media tablet observable */\nwindow.screen$ = screen$ /* Media screen observable */\nwindow.print$ = print$ /* Media print observable */\nwindow.alert$ = alert$ /* Alert subject */\nwindow.progress$ = progress$ /* Progress indicator subject */\nwindow.component$ = component$ /* Component observable */\n", "/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n", "/**\n * Returns true if the object is a function.\n * @param value The value to check\n */\nexport function isFunction(value: any): value is (...args: any[]) => any {\n return typeof value === 'function';\n}\n", "/**\n * Used to create Error subclasses until the community moves away from ES5.\n *\n * This is because compiling from TypeScript down to ES5 has issues with subclassing Errors\n * as well as other built-in types: https://github.com/Microsoft/TypeScript/issues/12123\n *\n * @param createImpl A factory function to create the actual constructor implementation. The returned\n * function should be a named function that calls `_super` internally.\n */\nexport function createErrorClass(createImpl: (_super: any) => any): T {\n const _super = (instance: any) => {\n Error.call(instance);\n instance.stack = new Error().stack;\n };\n\n const ctorFunc = createImpl(_super);\n ctorFunc.prototype = Object.create(Error.prototype);\n ctorFunc.prototype.constructor = ctorFunc;\n return ctorFunc;\n}\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface UnsubscriptionError extends Error {\n readonly errors: any[];\n}\n\nexport interface UnsubscriptionErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (errors: any[]): UnsubscriptionError;\n}\n\n/**\n * An error thrown when one or more errors have occurred during the\n * `unsubscribe` of a {@link Subscription}.\n */\nexport const UnsubscriptionError: UnsubscriptionErrorCtor = createErrorClass(\n (_super) =>\n function UnsubscriptionErrorImpl(this: any, errors: (Error | string)[]) {\n _super(this);\n this.message = errors\n ? `${errors.length} errors occurred during unsubscription:\n${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\\n ')}`\n : '';\n this.name = 'UnsubscriptionError';\n this.errors = errors;\n }\n);\n", "/**\n * Removes an item from an array, mutating it.\n * @param arr The array to remove the item from\n * @param item The item to remove\n */\nexport function arrRemove(arr: T[] | undefined | null, item: T) {\n if (arr) {\n const index = arr.indexOf(item);\n 0 <= index && arr.splice(index, 1);\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { UnsubscriptionError } from './util/UnsubscriptionError';\nimport { SubscriptionLike, TeardownLogic, Unsubscribable } from './types';\nimport { arrRemove } from './util/arrRemove';\n\n/**\n * Represents a disposable resource, such as the execution of an Observable. A\n * Subscription has one important method, `unsubscribe`, that takes no argument\n * and just disposes the resource held by the subscription.\n *\n * Additionally, subscriptions may be grouped together through the `add()`\n * method, which will attach a child Subscription to the current Subscription.\n * When a Subscription is unsubscribed, all its children (and its grandchildren)\n * will be unsubscribed as well.\n *\n * @class Subscription\n */\nexport class Subscription implements SubscriptionLike {\n /** @nocollapse */\n public static EMPTY = (() => {\n const empty = new Subscription();\n empty.closed = true;\n return empty;\n })();\n\n /**\n * A flag to indicate whether this Subscription has already been unsubscribed.\n */\n public closed = false;\n\n private _parentage: Subscription[] | Subscription | null = null;\n\n /**\n * The list of registered finalizers to execute upon unsubscription. Adding and removing from this\n * list occurs in the {@link #add} and {@link #remove} methods.\n */\n private _finalizers: Exclude[] | null = null;\n\n /**\n * @param initialTeardown A function executed first as part of the finalization\n * process that is kicked off when {@link #unsubscribe} is called.\n */\n constructor(private initialTeardown?: () => void) {}\n\n /**\n * Disposes the resources held by the subscription. May, for instance, cancel\n * an ongoing Observable execution or cancel any other type of work that\n * started when the Subscription was created.\n * @return {void}\n */\n unsubscribe(): void {\n let errors: any[] | undefined;\n\n if (!this.closed) {\n this.closed = true;\n\n // Remove this from it's parents.\n const { _parentage } = this;\n if (_parentage) {\n this._parentage = null;\n if (Array.isArray(_parentage)) {\n for (const parent of _parentage) {\n parent.remove(this);\n }\n } else {\n _parentage.remove(this);\n }\n }\n\n const { initialTeardown: initialFinalizer } = this;\n if (isFunction(initialFinalizer)) {\n try {\n initialFinalizer();\n } catch (e) {\n errors = e instanceof UnsubscriptionError ? e.errors : [e];\n }\n }\n\n const { _finalizers } = this;\n if (_finalizers) {\n this._finalizers = null;\n for (const finalizer of _finalizers) {\n try {\n execFinalizer(finalizer);\n } catch (err) {\n errors = errors ?? [];\n if (err instanceof UnsubscriptionError) {\n errors = [...errors, ...err.errors];\n } else {\n errors.push(err);\n }\n }\n }\n }\n\n if (errors) {\n throw new UnsubscriptionError(errors);\n }\n }\n }\n\n /**\n * Adds a finalizer to this subscription, so that finalization will be unsubscribed/called\n * when this subscription is unsubscribed. If this subscription is already {@link #closed},\n * because it has already been unsubscribed, then whatever finalizer is passed to it\n * will automatically be executed (unless the finalizer itself is also a closed subscription).\n *\n * Closed Subscriptions cannot be added as finalizers to any subscription. Adding a closed\n * subscription to a any subscription will result in no operation. (A noop).\n *\n * Adding a subscription to itself, or adding `null` or `undefined` will not perform any\n * operation at all. (A noop).\n *\n * `Subscription` instances that are added to this instance will automatically remove themselves\n * if they are unsubscribed. Functions and {@link Unsubscribable} objects that you wish to remove\n * will need to be removed manually with {@link #remove}\n *\n * @param teardown The finalization logic to add to this subscription.\n */\n add(teardown: TeardownLogic): void {\n // Only add the finalizer if it's not undefined\n // and don't add a subscription to itself.\n if (teardown && teardown !== this) {\n if (this.closed) {\n // If this subscription is already closed,\n // execute whatever finalizer is handed to it automatically.\n execFinalizer(teardown);\n } else {\n if (teardown instanceof Subscription) {\n // We don't add closed subscriptions, and we don't add the same subscription\n // twice. Subscription unsubscribe is idempotent.\n if (teardown.closed || teardown._hasParent(this)) {\n return;\n }\n teardown._addParent(this);\n }\n (this._finalizers = this._finalizers ?? []).push(teardown);\n }\n }\n }\n\n /**\n * Checks to see if a this subscription already has a particular parent.\n * This will signal that this subscription has already been added to the parent in question.\n * @param parent the parent to check for\n */\n private _hasParent(parent: Subscription) {\n const { _parentage } = this;\n return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));\n }\n\n /**\n * Adds a parent to this subscription so it can be removed from the parent if it\n * unsubscribes on it's own.\n *\n * NOTE: THIS ASSUMES THAT {@link _hasParent} HAS ALREADY BEEN CHECKED.\n * @param parent The parent subscription to add\n */\n private _addParent(parent: Subscription) {\n const { _parentage } = this;\n this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;\n }\n\n /**\n * Called on a child when it is removed via {@link #remove}.\n * @param parent The parent to remove\n */\n private _removeParent(parent: Subscription) {\n const { _parentage } = this;\n if (_parentage === parent) {\n this._parentage = null;\n } else if (Array.isArray(_parentage)) {\n arrRemove(_parentage, parent);\n }\n }\n\n /**\n * Removes a finalizer from this subscription that was previously added with the {@link #add} method.\n *\n * Note that `Subscription` instances, when unsubscribed, will automatically remove themselves\n * from every other `Subscription` they have been added to. This means that using the `remove` method\n * is not a common thing and should be used thoughtfully.\n *\n * If you add the same finalizer instance of a function or an unsubscribable object to a `Subscription` instance\n * more than once, you will need to call `remove` the same number of times to remove all instances.\n *\n * All finalizer instances are removed to free up memory upon unsubscription.\n *\n * @param teardown The finalizer to remove from this subscription\n */\n remove(teardown: Exclude): void {\n const { _finalizers } = this;\n _finalizers && arrRemove(_finalizers, teardown);\n\n if (teardown instanceof Subscription) {\n teardown._removeParent(this);\n }\n }\n}\n\nexport const EMPTY_SUBSCRIPTION = Subscription.EMPTY;\n\nexport function isSubscription(value: any): value is Subscription {\n return (\n value instanceof Subscription ||\n (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe))\n );\n}\n\nfunction execFinalizer(finalizer: Unsubscribable | (() => void)) {\n if (isFunction(finalizer)) {\n finalizer();\n } else {\n finalizer.unsubscribe();\n }\n}\n", "import { Subscriber } from './Subscriber';\nimport { ObservableNotification } from './types';\n\n/**\n * The {@link GlobalConfig} object for RxJS. It is used to configure things\n * like how to react on unhandled errors.\n */\nexport const config: GlobalConfig = {\n onUnhandledError: null,\n onStoppedNotification: null,\n Promise: undefined,\n useDeprecatedSynchronousErrorHandling: false,\n useDeprecatedNextContext: false,\n};\n\n/**\n * The global configuration object for RxJS, used to configure things\n * like how to react on unhandled errors. Accessible via {@link config}\n * object.\n */\nexport interface GlobalConfig {\n /**\n * A registration point for unhandled errors from RxJS. These are errors that\n * cannot were not handled by consuming code in the usual subscription path. For\n * example, if you have this configured, and you subscribe to an observable without\n * providing an error handler, errors from that subscription will end up here. This\n * will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onUnhandledError: ((err: any) => void) | null;\n\n /**\n * A registration point for notifications that cannot be sent to subscribers because they\n * have completed, errored or have been explicitly unsubscribed. By default, next, complete\n * and error notifications sent to stopped subscribers are noops. However, sometimes callers\n * might want a different behavior. For example, with sources that attempt to report errors\n * to stopped subscribers, a caller can configure RxJS to throw an unhandled error instead.\n * This will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onStoppedNotification: ((notification: ObservableNotification, subscriber: Subscriber) => void) | null;\n\n /**\n * The promise constructor used by default for {@link Observable#toPromise toPromise} and {@link Observable#forEach forEach}\n * methods.\n *\n * @deprecated As of version 8, RxJS will no longer support this sort of injection of a\n * Promise constructor. If you need a Promise implementation other than native promises,\n * please polyfill/patch Promise as you see appropriate. Will be removed in v8.\n */\n Promise?: PromiseConstructorLike;\n\n /**\n * If true, turns on synchronous error rethrowing, which is a deprecated behavior\n * in v6 and higher. This behavior enables bad patterns like wrapping a subscribe\n * call in a try/catch block. It also enables producer interference, a nasty bug\n * where a multicast can be broken for all observers by a downstream consumer with\n * an unhandled error. DO NOT USE THIS FLAG UNLESS IT'S NEEDED TO BUY TIME\n * FOR MIGRATION REASONS.\n *\n * @deprecated As of version 8, RxJS will no longer support synchronous throwing\n * of unhandled errors. All errors will be thrown on a separate call stack to prevent bad\n * behaviors described above. Will be removed in v8.\n */\n useDeprecatedSynchronousErrorHandling: boolean;\n\n /**\n * If true, enables an as-of-yet undocumented feature from v5: The ability to access\n * `unsubscribe()` via `this` context in `next` functions created in observers passed\n * to `subscribe`.\n *\n * This is being removed because the performance was severely problematic, and it could also cause\n * issues when types other than POJOs are passed to subscribe as subscribers, as they will likely have\n * their `this` context overwritten.\n *\n * @deprecated As of version 8, RxJS will no longer support altering the\n * context of next functions provided as part of an observer to Subscribe. Instead,\n * you will have access to a subscription or a signal or token that will allow you to do things like\n * unsubscribe and test closed status. Will be removed in v8.\n */\n useDeprecatedNextContext: boolean;\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetTimeoutFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearTimeoutFunction = (handle: TimerHandle) => void;\n\ninterface TimeoutProvider {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n delegate:\n | {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n }\n | undefined;\n}\n\nexport const timeoutProvider: TimeoutProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setTimeout(handler: () => void, timeout?: number, ...args) {\n const { delegate } = timeoutProvider;\n if (delegate?.setTimeout) {\n return delegate.setTimeout(handler, timeout, ...args);\n }\n return setTimeout(handler, timeout, ...args);\n },\n clearTimeout(handle) {\n const { delegate } = timeoutProvider;\n return (delegate?.clearTimeout || clearTimeout)(handle as any);\n },\n delegate: undefined,\n};\n", "import { config } from '../config';\nimport { timeoutProvider } from '../scheduler/timeoutProvider';\n\n/**\n * Handles an error on another job either with the user-configured {@link onUnhandledError},\n * or by throwing it on that new job so it can be picked up by `window.onerror`, `process.on('error')`, etc.\n *\n * This should be called whenever there is an error that is out-of-band with the subscription\n * or when an error hits a terminal boundary of the subscription and no error handler was provided.\n *\n * @param err the error to report\n */\nexport function reportUnhandledError(err: any) {\n timeoutProvider.setTimeout(() => {\n const { onUnhandledError } = config;\n if (onUnhandledError) {\n // Execute the user-configured error handler.\n onUnhandledError(err);\n } else {\n // Throw so it is picked up by the runtime's uncaught error mechanism.\n throw err;\n }\n });\n}\n", "/* tslint:disable:no-empty */\nexport function noop() { }\n", "import { CompleteNotification, NextNotification, ErrorNotification } from './types';\n\n/**\n * A completion object optimized for memory use and created to be the\n * same \"shape\" as other notifications in v8.\n * @internal\n */\nexport const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined) as CompleteNotification)();\n\n/**\n * Internal use only. Creates an optimized error notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function errorNotification(error: any): ErrorNotification {\n return createNotification('E', undefined, error) as any;\n}\n\n/**\n * Internal use only. Creates an optimized next notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function nextNotification(value: T) {\n return createNotification('N', value, undefined) as NextNotification;\n}\n\n/**\n * Ensures that all notifications created internally have the same \"shape\" in v8.\n *\n * TODO: This is only exported to support a crazy legacy test in `groupBy`.\n * @internal\n */\nexport function createNotification(kind: 'N' | 'E' | 'C', value: any, error: any) {\n return {\n kind,\n value,\n error,\n };\n}\n", "import { config } from '../config';\n\nlet context: { errorThrown: boolean; error: any } | null = null;\n\n/**\n * Handles dealing with errors for super-gross mode. Creates a context, in which\n * any synchronously thrown errors will be passed to {@link captureError}. Which\n * will record the error such that it will be rethrown after the call back is complete.\n * TODO: Remove in v8\n * @param cb An immediately executed function.\n */\nexport function errorContext(cb: () => void) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n const isRoot = !context;\n if (isRoot) {\n context = { errorThrown: false, error: null };\n }\n cb();\n if (isRoot) {\n const { errorThrown, error } = context!;\n context = null;\n if (errorThrown) {\n throw error;\n }\n }\n } else {\n // This is the general non-deprecated path for everyone that\n // isn't crazy enough to use super-gross mode (useDeprecatedSynchronousErrorHandling)\n cb();\n }\n}\n\n/**\n * Captures errors only in super-gross mode.\n * @param err the error to capture\n */\nexport function captureError(err: any) {\n if (config.useDeprecatedSynchronousErrorHandling && context) {\n context.errorThrown = true;\n context.error = err;\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { Observer, ObservableNotification } from './types';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nimport { captureError } from './util/errorContext';\n\n/**\n * Implements the {@link Observer} interface and extends the\n * {@link Subscription} class. While the {@link Observer} is the public API for\n * consuming the values of an {@link Observable}, all Observers get converted to\n * a Subscriber, in order to provide Subscription-like capabilities such as\n * `unsubscribe`. Subscriber is a common type in RxJS, and crucial for\n * implementing operators, but it is rarely used as a public API.\n *\n * @class Subscriber\n */\nexport class Subscriber extends Subscription implements Observer {\n /**\n * A static factory for a Subscriber, given a (potentially partial) definition\n * of an Observer.\n * @param next The `next` callback of an Observer.\n * @param error The `error` callback of an\n * Observer.\n * @param complete The `complete` callback of an\n * Observer.\n * @return A Subscriber wrapping the (partially defined)\n * Observer represented by the given arguments.\n * @nocollapse\n * @deprecated Do not use. Will be removed in v8. There is no replacement for this\n * method, and there is no reason to be creating instances of `Subscriber` directly.\n * If you have a specific use case, please file an issue.\n */\n static create(next?: (x?: T) => void, error?: (e?: any) => void, complete?: () => void): Subscriber {\n return new SafeSubscriber(next, error, complete);\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected isStopped: boolean = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected destination: Subscriber | Observer; // this `any` is the escape hatch to erase extra type param (e.g. R)\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * There is no reason to directly create an instance of Subscriber. This type is exported for typings reasons.\n */\n constructor(destination?: Subscriber | Observer) {\n super();\n if (destination) {\n this.destination = destination;\n // Automatically chain subscriptions together here.\n // if destination is a Subscription, then it is a Subscriber.\n if (isSubscription(destination)) {\n destination.add(this);\n }\n } else {\n this.destination = EMPTY_OBSERVER;\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `next` from\n * the Observable, with a value. The Observable may call this method 0 or more\n * times.\n * @param {T} [value] The `next` value.\n * @return {void}\n */\n next(value?: T): void {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n } else {\n this._next(value!);\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `error` from\n * the Observable, with an attached `Error`. Notifies the Observer that\n * the Observable has experienced an error condition.\n * @param {any} [err] The `error` exception.\n * @return {void}\n */\n error(err?: any): void {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n } else {\n this.isStopped = true;\n this._error(err);\n }\n }\n\n /**\n * The {@link Observer} callback to receive a valueless notification of type\n * `complete` from the Observable. Notifies the Observer that the Observable\n * has finished sending push-based notifications.\n * @return {void}\n */\n complete(): void {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n } else {\n this.isStopped = true;\n this._complete();\n }\n }\n\n unsubscribe(): void {\n if (!this.closed) {\n this.isStopped = true;\n super.unsubscribe();\n this.destination = null!;\n }\n }\n\n protected _next(value: T): void {\n this.destination.next(value);\n }\n\n protected _error(err: any): void {\n try {\n this.destination.error(err);\n } finally {\n this.unsubscribe();\n }\n }\n\n protected _complete(): void {\n try {\n this.destination.complete();\n } finally {\n this.unsubscribe();\n }\n }\n}\n\n/**\n * This bind is captured here because we want to be able to have\n * compatibility with monoid libraries that tend to use a method named\n * `bind`. In particular, a library called Monio requires this.\n */\nconst _bind = Function.prototype.bind;\n\nfunction bind any>(fn: Fn, thisArg: any): Fn {\n return _bind.call(fn, thisArg);\n}\n\n/**\n * Internal optimization only, DO NOT EXPOSE.\n * @internal\n */\nclass ConsumerObserver implements Observer {\n constructor(private partialObserver: Partial>) {}\n\n next(value: T): void {\n const { partialObserver } = this;\n if (partialObserver.next) {\n try {\n partialObserver.next(value);\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n\n error(err: any): void {\n const { partialObserver } = this;\n if (partialObserver.error) {\n try {\n partialObserver.error(err);\n } catch (error) {\n handleUnhandledError(error);\n }\n } else {\n handleUnhandledError(err);\n }\n }\n\n complete(): void {\n const { partialObserver } = this;\n if (partialObserver.complete) {\n try {\n partialObserver.complete();\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n}\n\nexport class SafeSubscriber extends Subscriber {\n constructor(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((e?: any) => void) | null,\n complete?: (() => void) | null\n ) {\n super();\n\n let partialObserver: Partial>;\n if (isFunction(observerOrNext) || !observerOrNext) {\n // The first argument is a function, not an observer. The next\n // two arguments *could* be observers, or they could be empty.\n partialObserver = {\n next: (observerOrNext ?? undefined) as (((value: T) => void) | undefined),\n error: error ?? undefined,\n complete: complete ?? undefined,\n };\n } else {\n // The first argument is a partial observer.\n let context: any;\n if (this && config.useDeprecatedNextContext) {\n // This is a deprecated path that made `this.unsubscribe()` available in\n // next handler functions passed to subscribe. This only exists behind a flag\n // now, as it is *very* slow.\n context = Object.create(observerOrNext);\n context.unsubscribe = () => this.unsubscribe();\n partialObserver = {\n next: observerOrNext.next && bind(observerOrNext.next, context),\n error: observerOrNext.error && bind(observerOrNext.error, context),\n complete: observerOrNext.complete && bind(observerOrNext.complete, context),\n };\n } else {\n // The \"normal\" path. Just use the partial observer directly.\n partialObserver = observerOrNext;\n }\n }\n\n // Wrap the partial observer to ensure it's a full observer, and\n // make sure proper error handling is accounted for.\n this.destination = new ConsumerObserver(partialObserver);\n }\n}\n\nfunction handleUnhandledError(error: any) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n captureError(error);\n } else {\n // Ideal path, we report this as an unhandled error,\n // which is thrown on a new call stack.\n reportUnhandledError(error);\n }\n}\n\n/**\n * An error handler used when no error handler was supplied\n * to the SafeSubscriber -- meaning no error handler was supplied\n * do the `subscribe` call on our observable.\n * @param err The error to handle\n */\nfunction defaultErrorHandler(err: any) {\n throw err;\n}\n\n/**\n * A handler for notifications that cannot be sent to a stopped subscriber.\n * @param notification The notification being sent\n * @param subscriber The stopped subscriber\n */\nfunction handleStoppedNotification(notification: ObservableNotification, subscriber: Subscriber) {\n const { onStoppedNotification } = config;\n onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));\n}\n\n/**\n * The observer used as a stub for subscriptions where the user did not\n * pass any arguments to `subscribe`. Comes with the default error handling\n * behavior.\n */\nexport const EMPTY_OBSERVER: Readonly> & { closed: true } = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop,\n};\n", "/**\n * Symbol.observable or a string \"@@observable\". Used for interop\n *\n * @deprecated We will no longer be exporting this symbol in upcoming versions of RxJS.\n * Instead polyfill and use Symbol.observable directly *or* use https://www.npmjs.com/package/symbol-observable\n */\nexport const observable: string | symbol = (() => (typeof Symbol === 'function' && Symbol.observable) || '@@observable')();\n", "/**\n * This function takes one parameter and just returns it. Simply put,\n * this is like `(x: T): T => x`.\n *\n * ## Examples\n *\n * This is useful in some cases when using things like `mergeMap`\n *\n * ```ts\n * import { interval, take, map, range, mergeMap, identity } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(5));\n *\n * const result$ = source$.pipe(\n * map(i => range(i)),\n * mergeMap(identity) // same as mergeMap(x => x)\n * );\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * Or when you want to selectively apply an operator\n *\n * ```ts\n * import { interval, take, identity } from 'rxjs';\n *\n * const shouldLimit = () => Math.random() < 0.5;\n *\n * const source$ = interval(1000);\n *\n * const result$ = source$.pipe(shouldLimit() ? take(5) : identity);\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * @param x Any value that is returned by this function\n * @returns The value passed as the first parameter to this function\n */\nexport function identity(x: T): T {\n return x;\n}\n", "import { identity } from './identity';\nimport { UnaryFunction } from '../types';\n\nexport function pipe(): typeof identity;\nexport function pipe(fn1: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction, fn3: UnaryFunction): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction,\n ...fns: UnaryFunction[]\n): UnaryFunction;\n\n/**\n * pipe() can be called on one or more functions, each of which can take one argument (\"UnaryFunction\")\n * and uses it to return a value.\n * It returns a function that takes one argument, passes it to the first UnaryFunction, and then\n * passes the result to the next one, passes that result to the next one, and so on. \n */\nexport function pipe(...fns: Array>): UnaryFunction {\n return pipeFromArray(fns);\n}\n\n/** @internal */\nexport function pipeFromArray(fns: Array>): UnaryFunction {\n if (fns.length === 0) {\n return identity as UnaryFunction;\n }\n\n if (fns.length === 1) {\n return fns[0];\n }\n\n return function piped(input: T): R {\n return fns.reduce((prev: any, fn: UnaryFunction) => fn(prev), input as any);\n };\n}\n", "import { Operator } from './Operator';\nimport { SafeSubscriber, Subscriber } from './Subscriber';\nimport { isSubscription, Subscription } from './Subscription';\nimport { TeardownLogic, OperatorFunction, Subscribable, Observer } from './types';\nimport { observable as Symbol_observable } from './symbol/observable';\nimport { pipeFromArray } from './util/pipe';\nimport { config } from './config';\nimport { isFunction } from './util/isFunction';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A representation of any set of values over any amount of time. This is the most basic building block\n * of RxJS.\n *\n * @class Observable\n */\nexport class Observable implements Subscribable {\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n source: Observable | undefined;\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n operator: Operator | undefined;\n\n /**\n * @constructor\n * @param {Function} subscribe the function that is called when the Observable is\n * initially subscribed to. This function is given a Subscriber, to which new values\n * can be `next`ed, or an `error` method can be called to raise an error, or\n * `complete` can be called to notify of a successful completion.\n */\n constructor(subscribe?: (this: Observable, subscriber: Subscriber) => TeardownLogic) {\n if (subscribe) {\n this._subscribe = subscribe;\n }\n }\n\n // HACK: Since TypeScript inherits static properties too, we have to\n // fight against TypeScript here so Subject can have a different static create signature\n /**\n * Creates a new Observable by calling the Observable constructor\n * @owner Observable\n * @method create\n * @param {Function} subscribe? the subscriber function to be passed to the Observable constructor\n * @return {Observable} a new observable\n * @nocollapse\n * @deprecated Use `new Observable()` instead. Will be removed in v8.\n */\n static create: (...args: any[]) => any = (subscribe?: (subscriber: Subscriber) => TeardownLogic) => {\n return new Observable(subscribe);\n };\n\n /**\n * Creates a new Observable, with this Observable instance as the source, and the passed\n * operator defined as the new observable's operator.\n * @method lift\n * @param operator the operator defining the operation to take on the observable\n * @return a new observable with the Operator applied\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * If you have implemented an operator using `lift`, it is recommended that you create an\n * operator by simply returning `new Observable()` directly. See \"Creating new operators from\n * scratch\" section here: https://rxjs.dev/guide/operators\n */\n lift(operator?: Operator): Observable {\n const observable = new Observable();\n observable.source = this;\n observable.operator = operator;\n return observable;\n }\n\n subscribe(observerOrNext?: Partial> | ((value: T) => void)): Subscription;\n /** @deprecated Instead of passing separate callback arguments, use an observer argument. Signatures taking separate callback arguments will be removed in v8. Details: https://rxjs.dev/deprecations/subscribe-arguments */\n subscribe(next?: ((value: T) => void) | null, error?: ((error: any) => void) | null, complete?: (() => void) | null): Subscription;\n /**\n * Invokes an execution of an Observable and registers Observer handlers for notifications it will emit.\n *\n * Use it when you have all these Observables, but still nothing is happening.\n *\n * `subscribe` is not a regular operator, but a method that calls Observable's internal `subscribe` function. It\n * might be for example a function that you passed to Observable's constructor, but most of the time it is\n * a library implementation, which defines what will be emitted by an Observable, and when it be will emitted. This means\n * that calling `subscribe` is actually the moment when Observable starts its work, not when it is created, as it is often\n * the thought.\n *\n * Apart from starting the execution of an Observable, this method allows you to listen for values\n * that an Observable emits, as well as for when it completes or errors. You can achieve this in two\n * of the following ways.\n *\n * The first way is creating an object that implements {@link Observer} interface. It should have methods\n * defined by that interface, but note that it should be just a regular JavaScript object, which you can create\n * yourself in any way you want (ES6 class, classic function constructor, object literal etc.). In particular, do\n * not attempt to use any RxJS implementation details to create Observers - you don't need them. Remember also\n * that your object does not have to implement all methods. If you find yourself creating a method that doesn't\n * do anything, you can simply omit it. Note however, if the `error` method is not provided and an error happens,\n * it will be thrown asynchronously. Errors thrown asynchronously cannot be caught using `try`/`catch`. Instead,\n * use the {@link onUnhandledError} configuration option or use a runtime handler (like `window.onerror` or\n * `process.on('error)`) to be notified of unhandled errors. Because of this, it's recommended that you provide\n * an `error` method to avoid missing thrown errors.\n *\n * The second way is to give up on Observer object altogether and simply provide callback functions in place of its methods.\n * This means you can provide three functions as arguments to `subscribe`, where the first function is equivalent\n * of a `next` method, the second of an `error` method and the third of a `complete` method. Just as in case of an Observer,\n * if you do not need to listen for something, you can omit a function by passing `undefined` or `null`,\n * since `subscribe` recognizes these functions by where they were placed in function call. When it comes\n * to the `error` function, as with an Observer, if not provided, errors emitted by an Observable will be thrown asynchronously.\n *\n * You can, however, subscribe with no parameters at all. This may be the case where you're not interested in terminal events\n * and you also handled emissions internally by using operators (e.g. using `tap`).\n *\n * Whichever style of calling `subscribe` you use, in both cases it returns a Subscription object.\n * This object allows you to call `unsubscribe` on it, which in turn will stop the work that an Observable does and will clean\n * up all resources that an Observable used. Note that cancelling a subscription will not call `complete` callback\n * provided to `subscribe` function, which is reserved for a regular completion signal that comes from an Observable.\n *\n * Remember that callbacks provided to `subscribe` are not guaranteed to be called asynchronously.\n * It is an Observable itself that decides when these functions will be called. For example {@link of}\n * by default emits all its values synchronously. Always check documentation for how given Observable\n * will behave when subscribed and if its default behavior can be modified with a `scheduler`.\n *\n * #### Examples\n *\n * Subscribe with an {@link guide/observer Observer}\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * const sumObserver = {\n * sum: 0,\n * next(value) {\n * console.log('Adding: ' + value);\n * this.sum = this.sum + value;\n * },\n * error() {\n * // We actually could just remove this method,\n * // since we do not really care about errors right now.\n * },\n * complete() {\n * console.log('Sum equals: ' + this.sum);\n * }\n * };\n *\n * of(1, 2, 3) // Synchronously emits 1, 2, 3 and then completes.\n * .subscribe(sumObserver);\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Subscribe with functions ({@link deprecations/subscribe-arguments deprecated})\n *\n * ```ts\n * import { of } from 'rxjs'\n *\n * let sum = 0;\n *\n * of(1, 2, 3).subscribe(\n * value => {\n * console.log('Adding: ' + value);\n * sum = sum + value;\n * },\n * undefined,\n * () => console.log('Sum equals: ' + sum)\n * );\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Cancel a subscription\n *\n * ```ts\n * import { interval } from 'rxjs';\n *\n * const subscription = interval(1000).subscribe({\n * next(num) {\n * console.log(num)\n * },\n * complete() {\n * // Will not be called, even when cancelling subscription.\n * console.log('completed!');\n * }\n * });\n *\n * setTimeout(() => {\n * subscription.unsubscribe();\n * console.log('unsubscribed!');\n * }, 2500);\n *\n * // Logs:\n * // 0 after 1s\n * // 1 after 2s\n * // 'unsubscribed!' after 2.5s\n * ```\n *\n * @param {Observer|Function} observerOrNext (optional) Either an observer with methods to be called,\n * or the first of three possible handlers, which is the handler for each value emitted from the subscribed\n * Observable.\n * @param {Function} error (optional) A handler for a terminal event resulting from an error. If no error handler is provided,\n * the error will be thrown asynchronously as unhandled.\n * @param {Function} complete (optional) A handler for a terminal event resulting from successful completion.\n * @return {Subscription} a subscription reference to the registered handlers\n * @method subscribe\n */\n subscribe(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((error: any) => void) | null,\n complete?: (() => void) | null\n ): Subscription {\n const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);\n\n errorContext(() => {\n const { operator, source } = this;\n subscriber.add(\n operator\n ? // We're dealing with a subscription in the\n // operator chain to one of our lifted operators.\n operator.call(subscriber, source)\n : source\n ? // If `source` has a value, but `operator` does not, something that\n // had intimate knowledge of our API, like our `Subject`, must have\n // set it. We're going to just call `_subscribe` directly.\n this._subscribe(subscriber)\n : // In all other cases, we're likely wrapping a user-provided initializer\n // function, so we need to catch errors and handle them appropriately.\n this._trySubscribe(subscriber)\n );\n });\n\n return subscriber;\n }\n\n /** @internal */\n protected _trySubscribe(sink: Subscriber): TeardownLogic {\n try {\n return this._subscribe(sink);\n } catch (err) {\n // We don't need to return anything in this case,\n // because it's just going to try to `add()` to a subscription\n // above.\n sink.error(err);\n }\n }\n\n /**\n * Used as a NON-CANCELLABLE means of subscribing to an observable, for use with\n * APIs that expect promises, like `async/await`. You cannot unsubscribe from this.\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * #### Example\n *\n * ```ts\n * import { interval, take } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(4));\n *\n * async function getTotal() {\n * let total = 0;\n *\n * await source$.forEach(value => {\n * total += value;\n * console.log('observable -> ' + value);\n * });\n *\n * return total;\n * }\n *\n * getTotal().then(\n * total => console.log('Total: ' + total)\n * );\n *\n * // Expected:\n * // 'observable -> 0'\n * // 'observable -> 1'\n * // 'observable -> 2'\n * // 'observable -> 3'\n * // 'Total: 6'\n * ```\n *\n * @param next a handler for each value emitted by the observable\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n */\n forEach(next: (value: T) => void): Promise;\n\n /**\n * @param next a handler for each value emitted by the observable\n * @param promiseCtor a constructor function used to instantiate the Promise\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n * @deprecated Passing a Promise constructor will no longer be available\n * in upcoming versions of RxJS. This is because it adds weight to the library, for very\n * little benefit. If you need this functionality, it is recommended that you either\n * polyfill Promise, or you create an adapter to convert the returned native promise\n * to whatever promise implementation you wanted. Will be removed in v8.\n */\n forEach(next: (value: T) => void, promiseCtor: PromiseConstructorLike): Promise;\n\n forEach(next: (value: T) => void, promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n const subscriber = new SafeSubscriber({\n next: (value) => {\n try {\n next(value);\n } catch (err) {\n reject(err);\n subscriber.unsubscribe();\n }\n },\n error: reject,\n complete: resolve,\n });\n this.subscribe(subscriber);\n }) as Promise;\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): TeardownLogic {\n return this.source?.subscribe(subscriber);\n }\n\n /**\n * An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable\n * @method Symbol.observable\n * @return {Observable} this instance of the observable\n */\n [Symbol_observable]() {\n return this;\n }\n\n /* tslint:disable:max-line-length */\n pipe(): Observable;\n pipe(op1: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction,\n ...operations: OperatorFunction[]\n ): Observable;\n /* tslint:enable:max-line-length */\n\n /**\n * Used to stitch together functional operators into a chain.\n * @method pipe\n * @return {Observable} the Observable result of all of the operators having\n * been called in the order they were passed in.\n *\n * ## Example\n *\n * ```ts\n * import { interval, filter, map, scan } from 'rxjs';\n *\n * interval(1000)\n * .pipe(\n * filter(x => x % 2 === 0),\n * map(x => x + x),\n * scan((acc, x) => acc + x)\n * )\n * .subscribe(x => console.log(x));\n * ```\n */\n pipe(...operations: OperatorFunction[]): Observable {\n return pipeFromArray(operations)(this);\n }\n\n /* tslint:disable:max-line-length */\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: typeof Promise): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: PromiseConstructorLike): Promise;\n /* tslint:enable:max-line-length */\n\n /**\n * Subscribe to this Observable and get a Promise resolving on\n * `complete` with the last emission (if any).\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * @method toPromise\n * @param [promiseCtor] a constructor function used to instantiate\n * the Promise\n * @return A Promise that resolves with the last value emit, or\n * rejects on an error. If there were no emissions, Promise\n * resolves with undefined.\n * @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise\n */\n toPromise(promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n let value: T | undefined;\n this.subscribe(\n (x: T) => (value = x),\n (err: any) => reject(err),\n () => resolve(value)\n );\n }) as Promise;\n }\n}\n\n/**\n * Decides between a passed promise constructor from consuming code,\n * A default configured promise constructor, and the native promise\n * constructor and returns it. If nothing can be found, it will throw\n * an error.\n * @param promiseCtor The optional promise constructor to passed by consuming code\n */\nfunction getPromiseCtor(promiseCtor: PromiseConstructorLike | undefined) {\n return promiseCtor ?? config.Promise ?? Promise;\n}\n\nfunction isObserver(value: any): value is Observer {\n return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);\n}\n\nfunction isSubscriber(value: any): value is Subscriber {\n return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));\n}\n", "import { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { OperatorFunction } from '../types';\nimport { isFunction } from './isFunction';\n\n/**\n * Used to determine if an object is an Observable with a lift function.\n */\nexport function hasLift(source: any): source is { lift: InstanceType['lift'] } {\n return isFunction(source?.lift);\n}\n\n/**\n * Creates an `OperatorFunction`. Used to define operators throughout the library in a concise way.\n * @param init The logic to connect the liftedSource to the subscriber at the moment of subscription.\n */\nexport function operate(\n init: (liftedSource: Observable, subscriber: Subscriber) => (() => void) | void\n): OperatorFunction {\n return (source: Observable) => {\n if (hasLift(source)) {\n return source.lift(function (this: Subscriber, liftedSource: Observable) {\n try {\n return init(liftedSource, this);\n } catch (err) {\n this.error(err);\n }\n });\n }\n throw new TypeError('Unable to lift unknown Observable type');\n };\n}\n", "import { Subscriber } from '../Subscriber';\n\n/**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional teardown logic here. This will only be called on teardown if the\n * subscriber itself is not already closed. This is called after all other teardown logic is executed.\n */\nexport function createOperatorSubscriber(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n onFinalize?: () => void\n): Subscriber {\n return new OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize);\n}\n\n/**\n * A generic helper for allowing operators to be created with a Subscriber and\n * use closures to capture necessary state from the operator function itself.\n */\nexport class OperatorSubscriber extends Subscriber {\n /**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional finalization logic here. This will only be called on finalization if the\n * subscriber itself is not already closed. This is called after all other finalization logic is executed.\n * @param shouldUnsubscribe An optional check to see if an unsubscribe call should truly unsubscribe.\n * NOTE: This currently **ONLY** exists to support the strange behavior of {@link groupBy}, where unsubscription\n * to the resulting observable does not actually disconnect from the source if there are active subscriptions\n * to any grouped observable. (DO NOT EXPOSE OR USE EXTERNALLY!!!)\n */\n constructor(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n private onFinalize?: () => void,\n private shouldUnsubscribe?: () => boolean\n ) {\n // It's important - for performance reasons - that all of this class's\n // members are initialized and that they are always initialized in the same\n // order. This will ensure that all OperatorSubscriber instances have the\n // same hidden class in V8. This, in turn, will help keep the number of\n // hidden classes involved in property accesses within the base class as\n // low as possible. If the number of hidden classes involved exceeds four,\n // the property accesses will become megamorphic and performance penalties\n // will be incurred - i.e. inline caches won't be used.\n //\n // The reasons for ensuring all instances have the same hidden class are\n // further discussed in this blog post from Benedikt Meurer:\n // https://benediktmeurer.de/2018/03/23/impact-of-polymorphism-on-component-based-frameworks-like-react/\n super(destination);\n this._next = onNext\n ? function (this: OperatorSubscriber, value: T) {\n try {\n onNext(value);\n } catch (err) {\n destination.error(err);\n }\n }\n : super._next;\n this._error = onError\n ? function (this: OperatorSubscriber, err: any) {\n try {\n onError(err);\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._error;\n this._complete = onComplete\n ? function (this: OperatorSubscriber) {\n try {\n onComplete();\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._complete;\n }\n\n unsubscribe() {\n if (!this.shouldUnsubscribe || this.shouldUnsubscribe()) {\n const { closed } = this;\n super.unsubscribe();\n // Execute additional teardown if we have any and we didn't already do so.\n !closed && this.onFinalize?.();\n }\n }\n}\n", "import { Subscription } from '../Subscription';\n\ninterface AnimationFrameProvider {\n schedule(callback: FrameRequestCallback): Subscription;\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n delegate:\n | {\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n }\n | undefined;\n}\n\nexport const animationFrameProvider: AnimationFrameProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n schedule(callback) {\n let request = requestAnimationFrame;\n let cancel: typeof cancelAnimationFrame | undefined = cancelAnimationFrame;\n const { delegate } = animationFrameProvider;\n if (delegate) {\n request = delegate.requestAnimationFrame;\n cancel = delegate.cancelAnimationFrame;\n }\n const handle = request((timestamp) => {\n // Clear the cancel function. The request has been fulfilled, so\n // attempting to cancel the request upon unsubscription would be\n // pointless.\n cancel = undefined;\n callback(timestamp);\n });\n return new Subscription(() => cancel?.(handle));\n },\n requestAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.requestAnimationFrame || requestAnimationFrame)(...args);\n },\n cancelAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.cancelAnimationFrame || cancelAnimationFrame)(...args);\n },\n delegate: undefined,\n};\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface ObjectUnsubscribedError extends Error {}\n\nexport interface ObjectUnsubscribedErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (): ObjectUnsubscribedError;\n}\n\n/**\n * An error thrown when an action is invalid because the object has been\n * unsubscribed.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n *\n * @class ObjectUnsubscribedError\n */\nexport const ObjectUnsubscribedError: ObjectUnsubscribedErrorCtor = createErrorClass(\n (_super) =>\n function ObjectUnsubscribedErrorImpl(this: any) {\n _super(this);\n this.name = 'ObjectUnsubscribedError';\n this.message = 'object unsubscribed';\n }\n);\n", "import { Operator } from './Operator';\nimport { Observable } from './Observable';\nimport { Subscriber } from './Subscriber';\nimport { Subscription, EMPTY_SUBSCRIPTION } from './Subscription';\nimport { Observer, SubscriptionLike, TeardownLogic } from './types';\nimport { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';\nimport { arrRemove } from './util/arrRemove';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A Subject is a special type of Observable that allows values to be\n * multicasted to many Observers. Subjects are like EventEmitters.\n *\n * Every Subject is an Observable and an Observer. You can subscribe to a\n * Subject, and you can call next to feed values as well as error and complete.\n */\nexport class Subject extends Observable implements SubscriptionLike {\n closed = false;\n\n private currentObservers: Observer[] | null = null;\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n observers: Observer[] = [];\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n isStopped = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n hasError = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n thrownError: any = null;\n\n /**\n * Creates a \"subject\" by basically gluing an observer to an observable.\n *\n * @nocollapse\n * @deprecated Recommended you do not use. Will be removed at some point in the future. Plans for replacement still under discussion.\n */\n static create: (...args: any[]) => any = (destination: Observer, source: Observable): AnonymousSubject => {\n return new AnonymousSubject(destination, source);\n };\n\n constructor() {\n // NOTE: This must be here to obscure Observable's constructor.\n super();\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n lift(operator: Operator): Observable {\n const subject = new AnonymousSubject(this, this);\n subject.operator = operator as any;\n return subject as any;\n }\n\n /** @internal */\n protected _throwIfClosed() {\n if (this.closed) {\n throw new ObjectUnsubscribedError();\n }\n }\n\n next(value: T) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n if (!this.currentObservers) {\n this.currentObservers = Array.from(this.observers);\n }\n for (const observer of this.currentObservers) {\n observer.next(value);\n }\n }\n });\n }\n\n error(err: any) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.hasError = this.isStopped = true;\n this.thrownError = err;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.error(err);\n }\n }\n });\n }\n\n complete() {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.isStopped = true;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.complete();\n }\n }\n });\n }\n\n unsubscribe() {\n this.isStopped = this.closed = true;\n this.observers = this.currentObservers = null!;\n }\n\n get observed() {\n return this.observers?.length > 0;\n }\n\n /** @internal */\n protected _trySubscribe(subscriber: Subscriber): TeardownLogic {\n this._throwIfClosed();\n return super._trySubscribe(subscriber);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._checkFinalizedStatuses(subscriber);\n return this._innerSubscribe(subscriber);\n }\n\n /** @internal */\n protected _innerSubscribe(subscriber: Subscriber) {\n const { hasError, isStopped, observers } = this;\n if (hasError || isStopped) {\n return EMPTY_SUBSCRIPTION;\n }\n this.currentObservers = null;\n observers.push(subscriber);\n return new Subscription(() => {\n this.currentObservers = null;\n arrRemove(observers, subscriber);\n });\n }\n\n /** @internal */\n protected _checkFinalizedStatuses(subscriber: Subscriber) {\n const { hasError, thrownError, isStopped } = this;\n if (hasError) {\n subscriber.error(thrownError);\n } else if (isStopped) {\n subscriber.complete();\n }\n }\n\n /**\n * Creates a new Observable with this Subject as the source. You can do this\n * to create custom Observer-side logic of the Subject and conceal it from\n * code that uses the Observable.\n * @return {Observable} Observable that the Subject casts to\n */\n asObservable(): Observable {\n const observable: any = new Observable();\n observable.source = this;\n return observable;\n }\n}\n\n/**\n * @class AnonymousSubject\n */\nexport class AnonymousSubject extends Subject {\n constructor(\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n public destination?: Observer,\n source?: Observable\n ) {\n super();\n this.source = source;\n }\n\n next(value: T) {\n this.destination?.next?.(value);\n }\n\n error(err: any) {\n this.destination?.error?.(err);\n }\n\n complete() {\n this.destination?.complete?.();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n return this.source?.subscribe(subscriber) ?? EMPTY_SUBSCRIPTION;\n }\n}\n", "import { TimestampProvider } from '../types';\n\ninterface DateTimestampProvider extends TimestampProvider {\n delegate: TimestampProvider | undefined;\n}\n\nexport const dateTimestampProvider: DateTimestampProvider = {\n now() {\n // Use the variable rather than `this` so that the function can be called\n // without being bound to the provider.\n return (dateTimestampProvider.delegate || Date).now();\n },\n delegate: undefined,\n};\n", "import { Subject } from './Subject';\nimport { TimestampProvider } from './types';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * A variant of {@link Subject} that \"replays\" old values to new subscribers by emitting them when they first subscribe.\n *\n * `ReplaySubject` has an internal buffer that will store a specified number of values that it has observed. Like `Subject`,\n * `ReplaySubject` \"observes\" values by having them passed to its `next` method. When it observes a value, it will store that\n * value for a time determined by the configuration of the `ReplaySubject`, as passed to its constructor.\n *\n * When a new subscriber subscribes to the `ReplaySubject` instance, it will synchronously emit all values in its buffer in\n * a First-In-First-Out (FIFO) manner. The `ReplaySubject` will also complete, if it has observed completion; and it will\n * error if it has observed an error.\n *\n * There are two main configuration items to be concerned with:\n *\n * 1. `bufferSize` - This will determine how many items are stored in the buffer, defaults to infinite.\n * 2. `windowTime` - The amount of time to hold a value in the buffer before removing it from the buffer.\n *\n * Both configurations may exist simultaneously. So if you would like to buffer a maximum of 3 values, as long as the values\n * are less than 2 seconds old, you could do so with a `new ReplaySubject(3, 2000)`.\n *\n * ### Differences with BehaviorSubject\n *\n * `BehaviorSubject` is similar to `new ReplaySubject(1)`, with a couple of exceptions:\n *\n * 1. `BehaviorSubject` comes \"primed\" with a single value upon construction.\n * 2. `ReplaySubject` will replay values, even after observing an error, where `BehaviorSubject` will not.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n * @see {@link shareReplay}\n */\nexport class ReplaySubject extends Subject {\n private _buffer: (T | number)[] = [];\n private _infiniteTimeWindow = true;\n\n /**\n * @param bufferSize The size of the buffer to replay on subscription\n * @param windowTime The amount of time the buffered items will stay buffered\n * @param timestampProvider An object with a `now()` method that provides the current timestamp. This is used to\n * calculate the amount of time something has been buffered.\n */\n constructor(\n private _bufferSize = Infinity,\n private _windowTime = Infinity,\n private _timestampProvider: TimestampProvider = dateTimestampProvider\n ) {\n super();\n this._infiniteTimeWindow = _windowTime === Infinity;\n this._bufferSize = Math.max(1, _bufferSize);\n this._windowTime = Math.max(1, _windowTime);\n }\n\n next(value: T): void {\n const { isStopped, _buffer, _infiniteTimeWindow, _timestampProvider, _windowTime } = this;\n if (!isStopped) {\n _buffer.push(value);\n !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);\n }\n this._trimBuffer();\n super.next(value);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._trimBuffer();\n\n const subscription = this._innerSubscribe(subscriber);\n\n const { _infiniteTimeWindow, _buffer } = this;\n // We use a copy here, so reentrant code does not mutate our array while we're\n // emitting it to a new subscriber.\n const copy = _buffer.slice();\n for (let i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {\n subscriber.next(copy[i] as T);\n }\n\n this._checkFinalizedStatuses(subscriber);\n\n return subscription;\n }\n\n private _trimBuffer() {\n const { _bufferSize, _timestampProvider, _buffer, _infiniteTimeWindow } = this;\n // If we don't have an infinite buffer size, and we're over the length,\n // use splice to truncate the old buffer values off. Note that we have to\n // double the size for instances where we're not using an infinite time window\n // because we're storing the values and the timestamps in the same array.\n const adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;\n _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);\n\n // Now, if we're not in an infinite time window, remove all values where the time is\n // older than what is allowed.\n if (!_infiniteTimeWindow) {\n const now = _timestampProvider.now();\n let last = 0;\n // Search the array for the first timestamp that isn't expired and\n // truncate the buffer up to that point.\n for (let i = 1; i < _buffer.length && (_buffer[i] as number) <= now; i += 2) {\n last = i;\n }\n last && _buffer.splice(0, last + 1);\n }\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Subscription } from '../Subscription';\nimport { SchedulerAction } from '../types';\n\n/**\n * A unit of work to be executed in a `scheduler`. An action is typically\n * created from within a {@link SchedulerLike} and an RxJS user does not need to concern\n * themselves about creating and manipulating an Action.\n *\n * ```ts\n * class Action extends Subscription {\n * new (scheduler: Scheduler, work: (state?: T) => void);\n * schedule(state?: T, delay: number = 0): Subscription;\n * }\n * ```\n *\n * @class Action\n */\nexport class Action extends Subscription {\n constructor(scheduler: Scheduler, work: (this: SchedulerAction, state?: T) => void) {\n super();\n }\n /**\n * Schedules this action on its parent {@link SchedulerLike} for execution. May be passed\n * some context object, `state`. May happen at some point in the future,\n * according to the `delay` parameter, if specified.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler.\n * @return {void}\n */\n public schedule(state?: T, delay: number = 0): Subscription {\n return this;\n }\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetIntervalFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearIntervalFunction = (handle: TimerHandle) => void;\n\ninterface IntervalProvider {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n delegate:\n | {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n }\n | undefined;\n}\n\nexport const intervalProvider: IntervalProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setInterval(handler: () => void, timeout?: number, ...args) {\n const { delegate } = intervalProvider;\n if (delegate?.setInterval) {\n return delegate.setInterval(handler, timeout, ...args);\n }\n return setInterval(handler, timeout, ...args);\n },\n clearInterval(handle) {\n const { delegate } = intervalProvider;\n return (delegate?.clearInterval || clearInterval)(handle as any);\n },\n delegate: undefined,\n};\n", "import { Action } from './Action';\nimport { SchedulerAction } from '../types';\nimport { Subscription } from '../Subscription';\nimport { AsyncScheduler } from './AsyncScheduler';\nimport { intervalProvider } from './intervalProvider';\nimport { arrRemove } from '../util/arrRemove';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncAction extends Action {\n public id: TimerHandle | undefined;\n public state?: T;\n // @ts-ignore: Property has no initializer and is not definitely assigned\n public delay: number;\n protected pending: boolean = false;\n\n constructor(protected scheduler: AsyncScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (this.closed) {\n return this;\n }\n\n // Always replace the current state with the new state.\n this.state = state;\n\n const id = this.id;\n const scheduler = this.scheduler;\n\n //\n // Important implementation note:\n //\n // Actions only execute once by default, unless rescheduled from within the\n // scheduled callback. This allows us to implement single and repeat\n // actions via the same code path, without adding API surface area, as well\n // as mimic traditional recursion but across asynchronous boundaries.\n //\n // However, JS runtimes and timers distinguish between intervals achieved by\n // serial `setTimeout` calls vs. a single `setInterval` call. An interval of\n // serial `setTimeout` calls can be individually delayed, which delays\n // scheduling the next `setTimeout`, and so on. `setInterval` attempts to\n // guarantee the interval callback will be invoked more precisely to the\n // interval period, regardless of load.\n //\n // Therefore, we use `setInterval` to schedule single and repeat actions.\n // If the action reschedules itself with the same delay, the interval is not\n // canceled. If the action doesn't reschedule, or reschedules with a\n // different delay, the interval will be canceled after scheduled callback\n // execution.\n //\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, delay);\n }\n\n // Set the pending flag indicating that this action has been scheduled, or\n // has recursively rescheduled itself.\n this.pending = true;\n\n this.delay = delay;\n // If this action has already an async Id, don't request a new one.\n this.id = this.id ?? this.requestAsyncId(scheduler, this.id, delay);\n\n return this;\n }\n\n protected requestAsyncId(scheduler: AsyncScheduler, _id?: TimerHandle, delay: number = 0): TimerHandle {\n return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n }\n\n protected recycleAsyncId(_scheduler: AsyncScheduler, id?: TimerHandle, delay: number | null = 0): TimerHandle | undefined {\n // If this action is rescheduled with the same delay time, don't clear the interval id.\n if (delay != null && this.delay === delay && this.pending === false) {\n return id;\n }\n // Otherwise, if the action's delay time is different from the current delay,\n // or the action has been rescheduled before it's executed, clear the interval id\n if (id != null) {\n intervalProvider.clearInterval(id);\n }\n\n return undefined;\n }\n\n /**\n * Immediately executes this action and the `work` it contains.\n * @return {any}\n */\n public execute(state: T, delay: number): any {\n if (this.closed) {\n return new Error('executing a cancelled action');\n }\n\n this.pending = false;\n const error = this._execute(state, delay);\n if (error) {\n return error;\n } else if (this.pending === false && this.id != null) {\n // Dequeue if the action didn't reschedule itself. Don't call\n // unsubscribe(), because the action could reschedule later.\n // For example:\n // ```\n // scheduler.schedule(function doWork(counter) {\n // /* ... I'm a busy worker bee ... */\n // var originalAction = this;\n // /* wait 100ms before rescheduling the action */\n // setTimeout(function () {\n // originalAction.schedule(counter + 1);\n // }, 100);\n // }, 1000);\n // ```\n this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n }\n }\n\n protected _execute(state: T, _delay: number): any {\n let errored: boolean = false;\n let errorValue: any;\n try {\n this.work(state);\n } catch (e) {\n errored = true;\n // HACK: Since code elsewhere is relying on the \"truthiness\" of the\n // return here, we can't have it return \"\" or 0 or false.\n // TODO: Clean this up when we refactor schedulers mid-version-8 or so.\n errorValue = e ? e : new Error('Scheduled action threw falsy error');\n }\n if (errored) {\n this.unsubscribe();\n return errorValue;\n }\n }\n\n unsubscribe() {\n if (!this.closed) {\n const { id, scheduler } = this;\n const { actions } = scheduler;\n\n this.work = this.state = this.scheduler = null!;\n this.pending = false;\n\n arrRemove(actions, this);\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, null);\n }\n\n this.delay = null!;\n super.unsubscribe();\n }\n }\n}\n", "import { Action } from './scheduler/Action';\nimport { Subscription } from './Subscription';\nimport { SchedulerLike, SchedulerAction } from './types';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * An execution context and a data structure to order tasks and schedule their\n * execution. Provides a notion of (potentially virtual) time, through the\n * `now()` getter method.\n *\n * Each unit of work in a Scheduler is called an `Action`.\n *\n * ```ts\n * class Scheduler {\n * now(): number;\n * schedule(work, delay?, state?): Subscription;\n * }\n * ```\n *\n * @class Scheduler\n * @deprecated Scheduler is an internal implementation detail of RxJS, and\n * should not be used directly. Rather, create your own class and implement\n * {@link SchedulerLike}. Will be made internal in v8.\n */\nexport class Scheduler implements SchedulerLike {\n public static now: () => number = dateTimestampProvider.now;\n\n constructor(private schedulerActionCtor: typeof Action, now: () => number = Scheduler.now) {\n this.now = now;\n }\n\n /**\n * A getter method that returns a number representing the current time\n * (at the time this function was called) according to the scheduler's own\n * internal clock.\n * @return {number} A number that represents the current time. May or may not\n * have a relation to wall-clock time. May or may not refer to a time unit\n * (e.g. milliseconds).\n */\n public now: () => number;\n\n /**\n * Schedules a function, `work`, for execution. May happen at some point in\n * the future, according to the `delay` parameter, if specified. May be passed\n * some context object, `state`, which will be passed to the `work` function.\n *\n * The given arguments will be processed an stored as an Action object in a\n * queue of actions.\n *\n * @param {function(state: ?T): ?Subscription} work A function representing a\n * task, or some unit of work to be executed by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler itself.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @return {Subscription} A subscription in order to be able to unsubscribe\n * the scheduled work.\n */\n public schedule(work: (this: SchedulerAction, state?: T) => void, delay: number = 0, state?: T): Subscription {\n return new this.schedulerActionCtor(this, work).schedule(state, delay);\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Action } from './Action';\nimport { AsyncAction } from './AsyncAction';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncScheduler extends Scheduler {\n public actions: Array> = [];\n /**\n * A flag to indicate whether the Scheduler is currently executing a batch of\n * queued actions.\n * @type {boolean}\n * @internal\n */\n public _active: boolean = false;\n /**\n * An internal ID used to track the latest asynchronous task such as those\n * coming from `setTimeout`, `setInterval`, `requestAnimationFrame`, and\n * others.\n * @type {any}\n * @internal\n */\n public _scheduled: TimerHandle | undefined;\n\n constructor(SchedulerAction: typeof Action, now: () => number = Scheduler.now) {\n super(SchedulerAction, now);\n }\n\n public flush(action: AsyncAction): void {\n const { actions } = this;\n\n if (this._active) {\n actions.push(action);\n return;\n }\n\n let error: any;\n this._active = true;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions.shift()!)); // exhaust the scheduler queue\n\n this._active = false;\n\n if (error) {\n while ((action = actions.shift()!)) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\n/**\n *\n * Async Scheduler\n *\n * Schedule task as if you used setTimeout(task, duration)\n *\n * `async` scheduler schedules tasks asynchronously, by putting them on the JavaScript\n * event loop queue. It is best used to delay tasks in time or to schedule tasks repeating\n * in intervals.\n *\n * If you just want to \"defer\" task, that is to perform it right after currently\n * executing synchronous code ends (commonly achieved by `setTimeout(deferredTask, 0)`),\n * better choice will be the {@link asapScheduler} scheduler.\n *\n * ## Examples\n * Use async scheduler to delay task\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * const task = () => console.log('it works!');\n *\n * asyncScheduler.schedule(task, 2000);\n *\n * // After 2 seconds logs:\n * // \"it works!\"\n * ```\n *\n * Use async scheduler to repeat task in intervals\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * function task(state) {\n * console.log(state);\n * this.schedule(state + 1, 1000); // `this` references currently executing Action,\n * // which we reschedule with new state and delay\n * }\n *\n * asyncScheduler.schedule(task, 3000, 0);\n *\n * // Logs:\n * // 0 after 3s\n * // 1 after 4s\n * // 2 after 5s\n * // 3 after 6s\n * ```\n */\n\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\n\n/**\n * @deprecated Renamed to {@link asyncScheduler}. Will be removed in v8.\n */\nexport const async = asyncScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\nimport { SchedulerAction } from '../types';\nimport { animationFrameProvider } from './animationFrameProvider';\nimport { TimerHandle } from './timerHandle';\n\nexport class AnimationFrameAction extends AsyncAction {\n constructor(protected scheduler: AnimationFrameScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n protected requestAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay is greater than 0, request as an async action.\n if (delay !== null && delay > 0) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n // Push the action to the end of the scheduler queue.\n scheduler.actions.push(this);\n // If an animation frame has already been requested, don't request another\n // one. If an animation frame hasn't been requested yet, request one. Return\n // the current animation frame request id.\n return scheduler._scheduled || (scheduler._scheduled = animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));\n }\n\n protected recycleAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n if (delay != null ? delay > 0 : this.delay > 0) {\n return super.recycleAsyncId(scheduler, id, delay);\n }\n // If the scheduler queue has no remaining actions with the same async id,\n // cancel the requested animation frame and set the scheduled flag to\n // undefined so the next AnimationFrameAction will request its own.\n const { actions } = scheduler;\n if (id != null && actions[actions.length - 1]?.id !== id) {\n animationFrameProvider.cancelAnimationFrame(id as number);\n scheduler._scheduled = undefined;\n }\n // Return undefined so the action knows to request a new async id if it's rescheduled.\n return undefined;\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\nexport class AnimationFrameScheduler extends AsyncScheduler {\n public flush(action?: AsyncAction): void {\n this._active = true;\n // The async id that effects a call to flush is stored in _scheduled.\n // Before executing an action, it's necessary to check the action's async\n // id to determine whether it's supposed to be executed in the current\n // flush.\n // Previous implementations of this method used a count to determine this,\n // but that was unsound, as actions that are unsubscribed - i.e. cancelled -\n // are removed from the actions array and that can shift actions that are\n // scheduled to be executed in a subsequent flush into positions at which\n // they are executed within the current flush.\n const flushId = this._scheduled;\n this._scheduled = undefined;\n\n const { actions } = this;\n let error: any;\n action = action || actions.shift()!;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions[0]) && action.id === flushId && actions.shift());\n\n this._active = false;\n\n if (error) {\n while ((action = actions[0]) && action.id === flushId && actions.shift()) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AnimationFrameAction } from './AnimationFrameAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\n\n/**\n *\n * Animation Frame Scheduler\n *\n * Perform task when `window.requestAnimationFrame` would fire\n *\n * When `animationFrame` scheduler is used with delay, it will fall back to {@link asyncScheduler} scheduler\n * behaviour.\n *\n * Without delay, `animationFrame` scheduler can be used to create smooth browser animations.\n * It makes sure scheduled task will happen just before next browser content repaint,\n * thus performing animations as efficiently as possible.\n *\n * ## Example\n * Schedule div height animation\n * ```ts\n * // html:
\n * import { animationFrameScheduler } from 'rxjs';\n *\n * const div = document.querySelector('div');\n *\n * animationFrameScheduler.schedule(function(height) {\n * div.style.height = height + \"px\";\n *\n * this.schedule(height + 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * }, 0, 0);\n *\n * // You will see a div element growing in height\n * ```\n */\n\nexport const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);\n\n/**\n * @deprecated Renamed to {@link animationFrameScheduler}. Will be removed in v8.\n */\nexport const animationFrame = animationFrameScheduler;\n", "import { Observable } from '../Observable';\nimport { SchedulerLike } from '../types';\n\n/**\n * A simple Observable that emits no items to the Observer and immediately\n * emits a complete notification.\n *\n * Just emits 'complete', and nothing else.\n *\n * ![](empty.png)\n *\n * A simple Observable that only emits the complete notification. It can be used\n * for composing with other Observables, such as in a {@link mergeMap}.\n *\n * ## Examples\n *\n * Log complete notification\n *\n * ```ts\n * import { EMPTY } from 'rxjs';\n *\n * EMPTY.subscribe({\n * next: () => console.log('Next'),\n * complete: () => console.log('Complete!')\n * });\n *\n * // Outputs\n * // Complete!\n * ```\n *\n * Emit the number 7, then complete\n *\n * ```ts\n * import { EMPTY, startWith } from 'rxjs';\n *\n * const result = EMPTY.pipe(startWith(7));\n * result.subscribe(x => console.log(x));\n *\n * // Outputs\n * // 7\n * ```\n *\n * Map and flatten only odd numbers to the sequence `'a'`, `'b'`, `'c'`\n *\n * ```ts\n * import { interval, mergeMap, of, EMPTY } from 'rxjs';\n *\n * const interval$ = interval(1000);\n * const result = interval$.pipe(\n * mergeMap(x => x % 2 === 1 ? of('a', 'b', 'c') : EMPTY),\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following to the console:\n * // x is equal to the count on the interval, e.g. (0, 1, 2, 3, ...)\n * // x will occur every 1000ms\n * // if x % 2 is equal to 1, print a, b, c (each on its own)\n * // if x % 2 is not equal to 1, nothing will be output\n * ```\n *\n * @see {@link Observable}\n * @see {@link NEVER}\n * @see {@link of}\n * @see {@link throwError}\n */\nexport const EMPTY = new Observable((subscriber) => subscriber.complete());\n\n/**\n * @param scheduler A {@link SchedulerLike} to use for scheduling\n * the emission of the complete notification.\n * @deprecated Replaced with the {@link EMPTY} constant or {@link scheduled} (e.g. `scheduled([], scheduler)`). Will be removed in v8.\n */\nexport function empty(scheduler?: SchedulerLike) {\n return scheduler ? emptyScheduled(scheduler) : EMPTY;\n}\n\nfunction emptyScheduled(scheduler: SchedulerLike) {\n return new Observable((subscriber) => scheduler.schedule(() => subscriber.complete()));\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport function isScheduler(value: any): value is SchedulerLike {\n return value && isFunction(value.schedule);\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\nimport { isScheduler } from './isScheduler';\n\nfunction last(arr: T[]): T | undefined {\n return arr[arr.length - 1];\n}\n\nexport function popResultSelector(args: any[]): ((...args: unknown[]) => unknown) | undefined {\n return isFunction(last(args)) ? args.pop() : undefined;\n}\n\nexport function popScheduler(args: any[]): SchedulerLike | undefined {\n return isScheduler(last(args)) ? args.pop() : undefined;\n}\n\nexport function popNumber(args: any[], defaultValue: number): number {\n return typeof last(args) === 'number' ? args.pop()! : defaultValue;\n}\n", "export const isArrayLike = ((x: any): x is ArrayLike => x && typeof x.length === 'number' && typeof x !== 'function');", "import { isFunction } from \"./isFunction\";\n\n/**\n * Tests to see if the object is \"thennable\".\n * @param value the object to test\n */\nexport function isPromise(value: any): value is PromiseLike {\n return isFunction(value?.then);\n}\n", "import { InteropObservable } from '../types';\nimport { observable as Symbol_observable } from '../symbol/observable';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being Observable (but not necessary an Rx Observable) */\nexport function isInteropObservable(input: any): input is InteropObservable {\n return isFunction(input[Symbol_observable]);\n}\n", "import { isFunction } from './isFunction';\n\nexport function isAsyncIterable(obj: any): obj is AsyncIterable {\n return Symbol.asyncIterator && isFunction(obj?.[Symbol.asyncIterator]);\n}\n", "/**\n * Creates the TypeError to throw if an invalid object is passed to `from` or `scheduled`.\n * @param input The object that was passed.\n */\nexport function createInvalidObservableTypeError(input: any) {\n // TODO: We should create error codes that can be looked up, so this can be less verbose.\n return new TypeError(\n `You provided ${\n input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`\n } where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`\n );\n}\n", "export function getSymbolIterator(): symbol {\n if (typeof Symbol !== 'function' || !Symbol.iterator) {\n return '@@iterator' as any;\n }\n\n return Symbol.iterator;\n}\n\nexport const iterator = getSymbolIterator();\n", "import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being an Iterable */\nexport function isIterable(input: any): input is Iterable {\n return isFunction(input?.[Symbol_iterator]);\n}\n", "import { ReadableStreamLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport async function* readableStreamLikeToAsyncGenerator(readableStream: ReadableStreamLike): AsyncGenerator {\n const reader = readableStream.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n return;\n }\n yield value!;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nexport function isReadableStreamLike(obj: any): obj is ReadableStreamLike {\n // We don't want to use instanceof checks because they would return\n // false for instances from another Realm, like an