text:
#==============================================================================#
# CodeBuild.jl
#
# This file is generated from:
# https://github.com/aws/aws-sdk-js/blob/master/apis/codebuild-2016-10-06.normal.json
#==============================================================================#

__precompile__()

module CodeBuild

using AWSCore

"""
    using AWSSDK.CodeBuild.batch_delete_builds
    batch_delete_builds([::AWSConfig], arguments::Dict)
    batch_delete_builds([::AWSConfig]; ids=)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "BatchDeleteBuilds", arguments::Dict)
    codebuild([::AWSConfig], "BatchDeleteBuilds", ids=)

# BatchDeleteBuilds Operation

Deletes one or more builds.

# Arguments

## `ids = [::String, ...]` -- *Required*
The IDs of the builds to delete.

# Returns

`BatchDeleteBuildsOutput`

# Exceptions

`InvalidInputException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/BatchDeleteBuilds)
"""
@inline batch_delete_builds(aws::AWSConfig=default_aws_config(); args...) = batch_delete_builds(aws, args)

@inline batch_delete_builds(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "BatchDeleteBuilds", args)

@inline batch_delete_builds(args) = batch_delete_builds(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.batch_get_builds
    batch_get_builds([::AWSConfig], arguments::Dict)
    batch_get_builds([::AWSConfig]; ids=)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "BatchGetBuilds", arguments::Dict)
    codebuild([::AWSConfig], "BatchGetBuilds", ids=)

# BatchGetBuilds Operation

Gets information about builds.

# Arguments

## `ids = [::String, ...]` -- *Required*
The IDs of the builds.

# Returns

`BatchGetBuildsOutput`

# Exceptions

`InvalidInputException`.

# Example: To get information about builds

The following example gets information about builds with the specified build IDs.

Input:
```
[
    "ids" => [
        "codebuild-demo-project:9b0ac37f-d19e-4254-9079-f47e9a389eEX",
        "codebuild-demo-project:b79a46f7-1473-4636-a23f-da9c45c208EX"
    ]
]
```

Output:
```
Dict(
    "builds" => [
        Dict(
            "arn" => "arn:aws:codebuild:us-east-1:123456789012:build/codebuild-demo-project:9b0ac37f-d19e-4254-9079-f47e9a389eEX",
            "artifacts" => Dict(
                "location" => "arn:aws:s3:::codebuild-123456789012-output-bucket/codebuild-demo-project"
            ),
            "buildComplete" => true,
            "buildStatus" => "SUCCEEDED",
            "currentPhase" => "COMPLETED",
            "endTime" => 1.479832474764e9,
            "environment" => Dict(
                "type" => "LINUX_CONTAINER",
                "computeType" => "BUILD_GENERAL1_SMALL",
                "environmentVariables" => [

                ],
                "image" => "aws/codebuild/java:openjdk-8",
                "privilegedMode" => false
            ),
            "id" => "codebuild-demo-project:9b0ac37f-d19e-4254-9079-f47e9a389eEX",
            "initiator" => "MyDemoUser",
            "logs" => Dict(
                "deepLink" => "https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logEvent:group=/aws/codebuild/codebuild-demo-project;stream=9b0ac37f-d19e-4254-9079-f47e9a389eEX",
                "groupName" => "/aws/codebuild/codebuild-demo-project",
                "streamName" => "9b0ac37f-d19e-4254-9079-f47e9a389eEX"
            ),
            "phases" => [
                Dict(
                    "durationInSeconds" => 0,
                    "endTime" => 1.47983234223e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "SUBMITTED",
                    "startTime" => 1.479832341854e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 72,
                    "endTime" => 1.479832415064e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "PROVISIONING",
                    "startTime" => 1.47983234223e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 46,
                    "endTime" => 1.479832461261e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "DOWNLOAD_SOURCE",
                    "startTime" => 1.479832415064e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 0,
                    "endTime" => 1.479832461354e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "INSTALL",
                    "startTime" => 1.479832461261e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 0,
                    "endTime" => 1.479832461448e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "PRE_BUILD",
                    "startTime" => 1.479832461354e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 9,
                    "endTime" => 1.479832471115e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "BUILD",
                    "startTime" => 1.479832461448e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 0,
                    "endTime" => 1.479832471224e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "POST_BUILD",
                    "startTime" => 1.479832471115e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 0,
                    "endTime" => 1.479832471791e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "UPLOAD_ARTIFACTS",
                    "startTime" => 1.479832471224e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 2,
                    "endTime" => 1.479832474764e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "FINALIZING",
                    "startTime" => 1.479832471791e9
                ),
                Dict(
                    "phaseType" => "COMPLETED",
                    "startTime" => 1.479832474764e9
                )
            ],
            "projectName" => "codebuild-demo-project",
            "source" => Dict(
                "type" => "S3",
                "buildspec" => "",
                "location" => "arn:aws:s3:::codebuild-123456789012-input-bucket/MessageUtil.zip"
            ),
            "startTime" => 1.479832341854e9,
            "timeoutInMinutes" => 60
        ),
        Dict(
            "arn" => "arn:aws:codebuild:us-east-1:123456789012:build/codebuild-demo-project:b79a46f7-1473-4636-a23f-da9c45c208EX",
            "artifacts" => Dict(
                "location" => "arn:aws:s3:::codebuild-123456789012-output-bucket/codebuild-demo-project"
            ),
            "buildComplete" => true,
            "buildStatus" => "SUCCEEDED",
            "currentPhase" => "COMPLETED",
            "endTime" => 1.479401214239e9,
            "environment" => Dict(
                "type" => "LINUX_CONTAINER",
                "computeType" => "BUILD_GENERAL1_SMALL",
                "environmentVariables" => [

                ],
                "image" => "aws/codebuild/java:openjdk-8",
                "privilegedMode" => false
            ),
            "id" => "codebuild-demo-project:b79a46f7-1473-4636-a23f-da9c45c208EX",
            "initiator" => "MyDemoUser",
            "logs" => Dict(
                "deepLink" => "https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logEvent:group=/aws/codebuild/codebuild-demo-project;stream=b79a46f7-1473-4636-a23f-da9c45c208EX",
                "groupName" => "/aws/codebuild/codebuild-demo-project",
                "streamName" => "b79a46f7-1473-4636-a23f-da9c45c208EX"
            ),
            "phases" => [
                Dict(
                    "durationInSeconds" => 0,
                    "endTime" => 1.479401082342e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "SUBMITTED",
                    "startTime" => 1.479401081869e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 71,
                    "endTime" => 1.479401154129e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "PROVISIONING",
                    "startTime" => 1.479401082342e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 45,
                    "endTime" => 1.479401199136e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "DOWNLOAD_SOURCE",
                    "startTime" => 1.479401154129e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 0,
                    "endTime" => 1.479401199236e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "INSTALL",
                    "startTime" => 1.479401199136e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 0,
                    "endTime" => 1.479401199345e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "PRE_BUILD",
                    "startTime" => 1.479401199236e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 9,
                    "endTime" => 1.47940120868e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "BUILD",
                    "startTime" => 1.479401199345e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 0,
                    "endTime" => 1.479401208783e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "POST_BUILD",
                    "startTime" => 1.47940120868e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 0,
                    "endTime" => 1.479401209463e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "UPLOAD_ARTIFACTS",
                    "startTime" => 1.479401208783e9
                ),
                Dict(
                    "contexts" => [

                    ],
                    "durationInSeconds" => 4,
                    "endTime" => 1.479401214239e9,
                    "phaseStatus" => "SUCCEEDED",
                    "phaseType" => "FINALIZING",
                    "startTime" => 1.479401209463e9
                ),
                Dict(
                    "phaseType" => "COMPLETED",
                    "startTime" => 1.479401214239e9
                )
            ],
            "projectName" => "codebuild-demo-project",
            "source" => Dict(
                "type" => "S3",
                "location" => "arn:aws:s3:::codebuild-123456789012-input-bucket/MessageUtil.zip"
            ),
            "startTime" => 1.479401081869e9,
            "timeoutInMinutes" => 60
        )
    ]
)
```

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/BatchGetBuilds)
"""
@inline batch_get_builds(aws::AWSConfig=default_aws_config(); args...) = batch_get_builds(aws, args)

@inline batch_get_builds(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "BatchGetBuilds", args)

@inline batch_get_builds(args) = batch_get_builds(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.batch_get_projects
    batch_get_projects([::AWSConfig], arguments::Dict)
    batch_get_projects([::AWSConfig]; names=)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "BatchGetProjects", arguments::Dict)
    codebuild([::AWSConfig], "BatchGetProjects", names=)

# BatchGetProjects Operation

Gets information about build projects.

# Arguments

## `names = [::String, ...]` -- *Required*
The names of the build projects.

# Returns

`BatchGetProjectsOutput`

# Exceptions

`InvalidInputException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/BatchGetProjects)
"""
@inline batch_get_projects(aws::AWSConfig=default_aws_config(); args...) = batch_get_projects(aws, args)

@inline batch_get_projects(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "BatchGetProjects", args)

@inline batch_get_projects(args) = batch_get_projects(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.create_project
    create_project([::AWSConfig], arguments::Dict)
    create_project([::AWSConfig]; name=, source=, artifacts=, environment=, serviceRole=, <keyword arguments>)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "CreateProject", arguments::Dict)
    codebuild([::AWSConfig], "CreateProject", name=, source=, artifacts=, environment=, serviceRole=, <keyword arguments>)

# CreateProject Operation

Creates a build project.

# Arguments

## `name = ::String` -- *Required*
The name of the build project.

## `description = ::String`
A description that makes the build project easy to identify.

## `source = [ ... ]` -- *Required*
Information about the build input source code for the build project.
```
 source = [
        "type" => <required> "CODECOMMIT", "CODEPIPELINE", "GITHUB", "S3", "BITBUCKET" or "GITHUB_ENTERPRISE",
        "location" =>  ::String,
        "gitCloneDepth" =>  ::Int,
        "buildspec" =>  ::String,
        "auth" =>  [
            "type" => <required> "OAUTH",
            "resource" =>  ::String
        ],
        "reportBuildStatus" =>  ::Bool,
        "insecureSsl" =>  ::Bool
    ]
```

## `artifacts = [ ... ]` -- *Required*
Information about the build output artifacts for the build project.
```
 artifacts = [
        "type" => <required> "CODEPIPELINE", "S3" or "NO_ARTIFACTS",
        "location" =>  ::String,
        "path" =>  ::String,
        "namespaceType" =>  "NONE" or "BUILD_ID",
        "name" =>  ::String,
        "packaging" =>  "NONE" or "ZIP",
        "encryptionDisabled" =>  ::Bool
    ]
```

## `cache = [ ... ]`
Stores recently used information so that it can be quickly accessed at a later time.
```
 cache = [
        "type" => <required> "NO_CACHE" or "S3",
        "location" =>  ::String
    ]
```

## `environment = [ ... ]` -- *Required*
Information about the build environment for the build project.
```
 environment = [
        "type" => <required> "WINDOWS_CONTAINER" or "LINUX_CONTAINER",
        "image" => <required> ::String,
        "computeType" => <required> "BUILD_GENERAL1_SMALL", "BUILD_GENERAL1_MEDIUM" or "BUILD_GENERAL1_LARGE",
        "environmentVariables" =>  [[
            "name" => <required> ::String,
            "value" => <required> ::String,
            "type" =>  "PLAINTEXT" or "PARAMETER_STORE"
        ], ...],
        "privilegedMode" =>  ::Bool,
        "certificate" =>  ::String
    ]
```

## `serviceRole = ::String` -- *Required*
The ARN of the AWS Identity and Access Management (IAM) role that enables AWS CodeBuild to interact with dependent AWS services on behalf of the AWS account.

## `timeoutInMinutes = ::Int`
How long, in minutes, from 5 to 480 (8 hours), for AWS CodeBuild to wait until timing out any build that has not been marked as completed. The default is 60 minutes.

## `encryptionKey = ::String`
The AWS Key Management Service (AWS KMS) customer master key (CMK) to be used for encrypting the build output artifacts.

You can specify either the CMK's Amazon Resource Name (ARN) or, if available, the CMK's alias (using the format `alias/*alias-name*` ).

## `tags = [[ ... ], ...]`
A set of tags for this build project.

These tags are available for use by AWS services that support AWS CodeBuild build project tags.
```
 tags = [[
        "key" =>  ::String,
        "value" =>  ::String
    ], ...]
```

## `vpcConfig = [ ... ]`
VpcConfig enables AWS CodeBuild to access resources in an Amazon VPC.
```
 vpcConfig = [
        "vpcId" =>  ::String,
        "subnets" =>  [::String, ...],
        "securityGroupIds" =>  [::String, ...]
    ]
```

## `badgeEnabled = ::Bool`
Set this to true to generate a publicly-accessible URL for your project's build badge.

# Returns

`CreateProjectOutput`

# Exceptions

`InvalidInputException`, `ResourceAlreadyExistsException` or `AccountLimitExceededException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/CreateProject)
"""
@inline create_project(aws::AWSConfig=default_aws_config(); args...) = create_project(aws, args)

@inline create_project(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "CreateProject", args)

@inline create_project(args) = create_project(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.create_webhook
    create_webhook([::AWSConfig], arguments::Dict)
    create_webhook([::AWSConfig]; projectName=, <keyword arguments>)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "CreateWebhook", arguments::Dict)
    codebuild([::AWSConfig], "CreateWebhook", projectName=, <keyword arguments>)

# CreateWebhook Operation

For an existing AWS CodeBuild build project that has its source code stored in a GitHub repository, enables AWS CodeBuild to begin automatically rebuilding the source code every time a code change is pushed to the repository.

**Important**
> If you enable webhooks for an AWS CodeBuild project, and the project is used as a build step in AWS CodePipeline, then two identical builds will be created for each commit. One build is triggered through webhooks, and one through AWS CodePipeline. Because billing is on a per-build basis, you will be billed for both builds. Therefore, if you are using AWS CodePipeline, we recommend that you disable webhooks in CodeBuild. In the AWS CodeBuild console, clear the Webhook box. For more information, see step 5 in [Change a Build Project's Settings](http://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html#change-project-console).

# Arguments

## `projectName = ::String` -- *Required*
The name of the AWS CodeBuild project.

## `branchFilter = ::String`
A regular expression used to determine which branches in a repository are built when a webhook is triggered. If the name of a branch matches the regular expression, then it is built. If it doesn't match, then it is not. If branchFilter is empty, then all branches are built.

# Returns

`CreateWebhookOutput`

# Exceptions

`InvalidInputException`, `OAuthProviderException`, `ResourceAlreadyExistsException` or `ResourceNotFoundException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/CreateWebhook)
"""
@inline create_webhook(aws::AWSConfig=default_aws_config(); args...) = create_webhook(aws, args)

@inline create_webhook(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "CreateWebhook", args)

@inline create_webhook(args) = create_webhook(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.delete_project
    delete_project([::AWSConfig], arguments::Dict)
    delete_project([::AWSConfig]; name=)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "DeleteProject", arguments::Dict)
    codebuild([::AWSConfig], "DeleteProject", name=)

# DeleteProject Operation

Deletes a build project.

# Arguments

## `name = ::String` -- *Required*
The name of the build project.

# Returns

`DeleteProjectOutput`

# Exceptions

`InvalidInputException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/DeleteProject)
"""
@inline delete_project(aws::AWSConfig=default_aws_config(); args...) = delete_project(aws, args)

@inline delete_project(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "DeleteProject", args)

@inline delete_project(args) = delete_project(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.delete_webhook
    delete_webhook([::AWSConfig], arguments::Dict)
    delete_webhook([::AWSConfig]; projectName=)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "DeleteWebhook", arguments::Dict)
    codebuild([::AWSConfig], "DeleteWebhook", projectName=)

# DeleteWebhook Operation

For an existing AWS CodeBuild build project that has its source code stored in a GitHub repository, stops AWS CodeBuild from automatically rebuilding the source code every time a code change is pushed to the repository.

# Arguments

## `projectName = ::String` -- *Required*
The name of the AWS CodeBuild project.

# Returns

`DeleteWebhookOutput`

# Exceptions

`InvalidInputException`, `ResourceNotFoundException` or `OAuthProviderException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/DeleteWebhook)
"""
@inline delete_webhook(aws::AWSConfig=default_aws_config(); args...) = delete_webhook(aws, args)

@inline delete_webhook(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "DeleteWebhook", args)

@inline delete_webhook(args) = delete_webhook(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.invalidate_project_cache
    invalidate_project_cache([::AWSConfig], arguments::Dict)
    invalidate_project_cache([::AWSConfig]; projectName=)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "InvalidateProjectCache", arguments::Dict)
    codebuild([::AWSConfig], "InvalidateProjectCache", projectName=)

# InvalidateProjectCache Operation

Resets the cache for a project.

# Arguments

## `projectName = ::String` -- *Required*
The name of the AWS CodeBuild build project that the cache will be reset for.

# Returns

`InvalidateProjectCacheOutput`

# Exceptions

`InvalidInputException` or `ResourceNotFoundException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/InvalidateProjectCache)
"""
@inline invalidate_project_cache(aws::AWSConfig=default_aws_config(); args...) = invalidate_project_cache(aws, args)

@inline invalidate_project_cache(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "InvalidateProjectCache", args)

@inline invalidate_project_cache(args) = invalidate_project_cache(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.list_builds
    list_builds([::AWSConfig], arguments::Dict)
    list_builds([::AWSConfig]; <keyword arguments>)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "ListBuilds", arguments::Dict)
    codebuild([::AWSConfig], "ListBuilds", <keyword arguments>)

# ListBuilds Operation

Gets a list of build IDs, with each build ID representing a single build.

# Arguments

## `sortOrder = "ASCENDING" or "DESCENDING"`
The order to list build IDs. Valid values include:

*   `ASCENDING`: List the build IDs in ascending order by build ID.

*   `DESCENDING`: List the build IDs in descending order by build ID.

## `nextToken = ::String`
During a previous call, if there are more than 100 items in the list, only the first 100 items are returned, along with a unique string called a *next token*. To get the next batch of items in the list, call this operation again, adding the next token to the call. To get all of the items in the list, keep calling this operation with each subsequent next token that is returned, until no more next tokens are returned.

# Returns

`ListBuildsOutput`

# Exceptions

`InvalidInputException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/ListBuilds)
"""
@inline list_builds(aws::AWSConfig=default_aws_config(); args...) = list_builds(aws, args)

@inline list_builds(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "ListBuilds", args)

@inline list_builds(args) = list_builds(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.list_builds_for_project
    list_builds_for_project([::AWSConfig], arguments::Dict)
    list_builds_for_project([::AWSConfig]; projectName=, <keyword arguments>)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "ListBuildsForProject", arguments::Dict)
    codebuild([::AWSConfig], "ListBuildsForProject", projectName=, <keyword arguments>)

# ListBuildsForProject Operation

Gets a list of build IDs for the specified build project, with each build ID representing a single build.

# Arguments

## `projectName = ::String` -- *Required*
The name of the AWS CodeBuild project.

## `sortOrder = "ASCENDING" or "DESCENDING"`
The order to list build IDs. Valid values include:

*   `ASCENDING`: List the build IDs in ascending order by build ID.

*   `DESCENDING`: List the build IDs in descending order by build ID.

## `nextToken = ::String`
During a previous call, if there are more than 100 items in the list, only the first 100 items are returned, along with a unique string called a *next token*. To get the next batch of items in the list, call this operation again, adding the next token to the call. To get all of the items in the list, keep calling this operation with each subsequent next token that is returned, until no more next tokens are returned.

# Returns

`ListBuildsForProjectOutput`

# Exceptions

`InvalidInputException` or `ResourceNotFoundException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/ListBuildsForProject)
"""
@inline list_builds_for_project(aws::AWSConfig=default_aws_config(); args...) = list_builds_for_project(aws, args)

@inline list_builds_for_project(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "ListBuildsForProject", args)

@inline list_builds_for_project(args) = list_builds_for_project(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.list_curated_environment_images
    list_curated_environment_images([::AWSConfig], arguments::Dict)
    list_curated_environment_images([::AWSConfig]; )

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "ListCuratedEnvironmentImages", arguments::Dict)
    codebuild([::AWSConfig], "ListCuratedEnvironmentImages", )

# ListCuratedEnvironmentImages Operation

Gets information about Docker images that are managed by AWS CodeBuild.

# Arguments

# Returns

`ListCuratedEnvironmentImagesOutput`

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/ListCuratedEnvironmentImages)
"""
@inline list_curated_environment_images(aws::AWSConfig=default_aws_config(); args...) = list_curated_environment_images(aws, args)

@inline list_curated_environment_images(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "ListCuratedEnvironmentImages", args)

@inline list_curated_environment_images(args) = list_curated_environment_images(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.list_projects
    list_projects([::AWSConfig], arguments::Dict)
    list_projects([::AWSConfig]; <keyword arguments>)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "ListProjects", arguments::Dict)
    codebuild([::AWSConfig], "ListProjects", <keyword arguments>)

# ListProjects Operation

Gets a list of build project names, with each build project name representing a single build project.

# Arguments

## `sortBy = "NAME", "CREATED_TIME" or "LAST_MODIFIED_TIME"`
The criterion to be used to list build project names. Valid values include:

*   `CREATED_TIME`: List the build project names based on when each build project was created.

*   `LAST_MODIFIED_TIME`: List the build project names based on when information about each build project was last changed.

*   `NAME`: List the build project names based on each build project's name.

Use `sortOrder` to specify in what order to list the build project names based on the preceding criteria.

## `sortOrder = "ASCENDING" or "DESCENDING"`
The order in which to list build projects. Valid values include:

*   `ASCENDING`: List the build project names in ascending order.

*   `DESCENDING`: List the build project names in descending order.

Use `sortBy` to specify the criterion to be used to list build project names.

## `nextToken = ::String`
During a previous call, if there are more than 100 items in the list, only the first 100 items are returned, along with a unique string called a *next token*. To get the next batch of items in the list, call this operation again, adding the next token to the call. To get all of the items in the list, keep calling this operation with each subsequent next token that is returned, until no more next tokens are returned.

# Returns

`ListProjectsOutput`

# Exceptions

`InvalidInputException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/ListProjects)
"""
@inline list_projects(aws::AWSConfig=default_aws_config(); args...) = list_projects(aws, args)

@inline list_projects(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "ListProjects", args)

@inline list_projects(args) = list_projects(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.start_build
    start_build([::AWSConfig], arguments::Dict)
    start_build([::AWSConfig]; projectName=, <keyword arguments>)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "StartBuild", arguments::Dict)
    codebuild([::AWSConfig], "StartBuild", projectName=, <keyword arguments>)

# StartBuild Operation

Starts running a build.

# Arguments

## `projectName = ::String` -- *Required*
The name of the AWS CodeBuild build project to start running a build.

## `sourceVersion = ::String`
A version of the build input to be built, for this build only. If not specified, the latest version will be used. If specified, must be one of:

*   For AWS CodeCommit: the commit ID to use.

*   For GitHub: the commit ID, pull request ID, branch name, or tag name that corresponds to the version of the source code you want to build. If a pull request ID is specified, it must use the format `pr/pull-request-ID` (for example `pr/25`). If a branch name is specified, the branch's HEAD commit ID will be used. If not specified, the default branch's HEAD commit ID will be used.

*   For Bitbucket: the commit ID, branch name, or tag name that corresponds to the version of the source code you want to build. If a branch name is specified, the branch's HEAD commit ID will be used. If not specified, the default branch's HEAD commit ID will be used.

*   For Amazon Simple Storage Service (Amazon S3): the version ID of the object representing the build input ZIP file to use.

## `artifactsOverride = [ ... ]`
Build output artifact settings that override, for this build only, the latest ones already defined in the build project.
```
 artifactsOverride = [
        "type" => <required> "CODEPIPELINE", "S3" or "NO_ARTIFACTS",
        "location" =>  ::String,
        "path" =>  ::String,
        "namespaceType" =>  "NONE" or "BUILD_ID",
        "name" =>  ::String,
        "packaging" =>  "NONE" or "ZIP",
        "encryptionDisabled" =>  ::Bool
    ]
```

## `environmentVariablesOverride = [[ ... ], ...]`
A set of environment variables that overrides, for this build only, the latest ones already defined in the build project.
```
 environmentVariablesOverride = [[
        "name" => <required> ::String,
        "value" => <required> ::String,
        "type" =>  "PLAINTEXT" or "PARAMETER_STORE"
    ], ...]
```

## `sourceTypeOverride = "CODECOMMIT", "CODEPIPELINE", "GITHUB", "S3", "BITBUCKET" or "GITHUB_ENTERPRISE"`
A source input type for this build that overrides the source input defined in the build project

## `sourceLocationOverride = ::String`
A location that overrides for this build the source location for the one defined in the build project.

## `sourceAuthOverride = [ ... ]`
An authorization type for this build that overrides the one defined in the build project. This override applies only if the build project's source is BitBucket or GitHub.
```
 sourceAuthOverride = [
        "type" => <required> "OAUTH",
        "resource" =>  ::String
    ]
```

## `gitCloneDepthOverride = ::Int`
The user-defined depth of history, with a minimum value of 0, that overrides, for this build only, any previous depth of history defined in the build project.

## `buildspecOverride = ::String`
A build spec declaration that overrides, for this build only, the latest one already defined in the build project.

## `insecureSslOverride = ::Bool`
Enable this flag to override the insecure SSL setting that is specified in the build project. The insecure SSL setting determines whether to ignore SSL warnings while connecting to the project source code. This override applies only if the build's source is GitHub Enterprise.

## `reportBuildStatusOverride = ::Bool`
Set to true to report to your source provider the status of a build's start and completion. If you use this option with a source provider other than GitHub, an invalidInputException is thrown.

## `environmentTypeOverride = "WINDOWS_CONTAINER" or "LINUX_CONTAINER"`
A container type for this build that overrides the one specified in the build project.

## `imageOverride = ::String`
The name of an image for this build that overrides the one specified in the build project.

## `computeTypeOverride = "BUILD_GENERAL1_SMALL", "BUILD_GENERAL1_MEDIUM" or "BUILD_GENERAL1_LARGE"`
The name of a compute type for this build that overrides the one specified in the build project.

## `certificateOverride = ::String`
The name of a certificate for this build that overrides the one specified in the build project.

## `cacheOverride = [ ... ]`
A ProjectCache object specified for this build that overrides the one defined in the build project.
```
 cacheOverride = [
        "type" => <required> "NO_CACHE" or "S3",
        "location" =>  ::String
    ]
```

## `serviceRoleOverride = ::String`
The name of a service role for this build that overrides the one specified in the build project.

## `privilegedModeOverride = ::Bool`
Enable this flag to override privileged mode in the build project.

## `timeoutInMinutesOverride = ::Int`
The number of build timeout minutes, from 5 to 480 (8 hours), that overrides, for this build only, the latest setting already defined in the build project.

## `idempotencyToken = ::String`
A unique, case sensitive identifier you provide to ensure the idempotency of the StartBuild request. The token is included in the StartBuild request and is valid for 12 hours. If you repeat the StartBuild request with the same token, but change a parameter, AWS CodeBuild returns a parameter mismatch error.

# Returns

`StartBuildOutput`

# Exceptions

`InvalidInputException`, `ResourceNotFoundException` or `AccountLimitExceededException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/StartBuild)
"""
@inline start_build(aws::AWSConfig=default_aws_config(); args...) = start_build(aws, args)

@inline start_build(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "StartBuild", args)

@inline start_build(args) = start_build(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.stop_build
    stop_build([::AWSConfig], arguments::Dict)
    stop_build([::AWSConfig]; id=)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "StopBuild", arguments::Dict)
    codebuild([::AWSConfig], "StopBuild", id=)

# StopBuild Operation

Attempts to stop running a build.

# Arguments

## `id = ::String` -- *Required*
The ID of the build.

# Returns

`StopBuildOutput`

# Exceptions

`InvalidInputException` or `ResourceNotFoundException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/StopBuild)
"""
@inline stop_build(aws::AWSConfig=default_aws_config(); args...) = stop_build(aws, args)

@inline stop_build(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "StopBuild", args)

@inline stop_build(args) = stop_build(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.update_project
    update_project([::AWSConfig], arguments::Dict)
    update_project([::AWSConfig]; name=, <keyword arguments>)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "UpdateProject", arguments::Dict)
    codebuild([::AWSConfig], "UpdateProject", name=, <keyword arguments>)

# UpdateProject Operation

Changes the settings of a build project.

# Arguments

## `name = ::String` -- *Required*
The name of the build project.

**Note**
> You cannot change a build project's name.

## `description = ::String`
A new or replacement description of the build project.

## `source = [ ... ]`
Information to be changed about the build input source code for the build project.
```
 source = [
        "type" => <required> "CODECOMMIT", "CODEPIPELINE", "GITHUB", "S3", "BITBUCKET" or "GITHUB_ENTERPRISE",
        "location" =>  ::String,
        "gitCloneDepth" =>  ::Int,
        "buildspec" =>  ::String,
        "auth" =>  [
            "type" => <required> "OAUTH",
            "resource" =>  ::String
        ],
        "reportBuildStatus" =>  ::Bool,
        "insecureSsl" =>  ::Bool
    ]
```

## `artifacts = [ ... ]`
Information to be changed about the build output artifacts for the build project.
```
 artifacts = [
        "type" => <required> "CODEPIPELINE", "S3" or "NO_ARTIFACTS",
        "location" =>  ::String,
        "path" =>  ::String,
        "namespaceType" =>  "NONE" or "BUILD_ID",
        "name" =>  ::String,
        "packaging" =>  "NONE" or "ZIP",
        "encryptionDisabled" =>  ::Bool
    ]
```

## `cache = [ ... ]`
Stores recently used information so that it can be quickly accessed at a later time.
```
 cache = [
        "type" => <required> "NO_CACHE" or "S3",
        "location" =>  ::String
    ]
```

## `environment = [ ... ]`
Information to be changed about the build environment for the build project.
```
 environment = [
        "type" => <required> "WINDOWS_CONTAINER" or "LINUX_CONTAINER",
        "image" => <required> ::String,
        "computeType" => <required> "BUILD_GENERAL1_SMALL", "BUILD_GENERAL1_MEDIUM" or "BUILD_GENERAL1_LARGE",
        "environmentVariables" =>  [[
            "name" => <required> ::String,
            "value" => <required> ::String,
            "type" =>  "PLAINTEXT" or "PARAMETER_STORE"
        ], ...],
        "privilegedMode" =>  ::Bool,
        "certificate" =>  ::String
    ]
```

## `serviceRole = ::String`
The replacement ARN of the AWS Identity and Access Management (IAM) role that enables AWS CodeBuild to interact with dependent AWS services on behalf of the AWS account.

## `timeoutInMinutes = ::Int`
The replacement value in minutes, from 5 to 480 (8 hours), for AWS CodeBuild to wait before timing out any related build that did not get marked as completed.

## `encryptionKey = ::String`
The replacement AWS Key Management Service (AWS KMS) customer master key (CMK) to be used for encrypting the build output artifacts.

You can specify either the CMK's Amazon Resource Name (ARN) or, if available, the CMK's alias (using the format `alias/*alias-name*` ).

## `tags = [[ ... ], ...]`
The replacement set of tags for this build project.

These tags are available for use by AWS services that support AWS CodeBuild build project tags.
```
 tags = [[
        "key" =>  ::String,
        "value" =>  ::String
    ], ...]
```

## `vpcConfig = [ ... ]`
VpcConfig enables AWS CodeBuild to access resources in an Amazon VPC.
```
 vpcConfig = [
        "vpcId" =>  ::String,
        "subnets" =>  [::String, ...],
        "securityGroupIds" =>  [::String, ...]
    ]
```

## `badgeEnabled = ::Bool`
Set this to true to generate a publicly-accessible URL for your project's build badge.

# Returns

`UpdateProjectOutput`

# Exceptions

`InvalidInputException` or `ResourceNotFoundException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/UpdateProject)
"""
@inline update_project(aws::AWSConfig=default_aws_config(); args...) = update_project(aws, args)

@inline update_project(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "UpdateProject", args)

@inline update_project(args) = update_project(default_aws_config(), args)

"""
    using AWSSDK.CodeBuild.update_webhook
    update_webhook([::AWSConfig], arguments::Dict)
    update_webhook([::AWSConfig]; projectName=, <keyword arguments>)

    using AWSCore.Services.codebuild
    codebuild([::AWSConfig], "UpdateWebhook", arguments::Dict)
    codebuild([::AWSConfig], "UpdateWebhook", projectName=, <keyword arguments>)

# UpdateWebhook Operation

Updates the webhook associated with an AWS CodeBuild build project.

# Arguments

## `projectName = ::String` -- *Required*
The name of the AWS CodeBuild project.

## `branchFilter = ::String`
A regular expression used to determine which branches in a repository are built when a webhook is triggered. If the name of a branch matches the regular expression, then it is built. If it doesn't match, then it is not. If branchFilter is empty, then all branches are built.

## `rotateSecret = ::Bool`
A boolean value that specifies whether the associated repository's secret token should be updated.

# Returns

`UpdateWebhookOutput`

# Exceptions

`InvalidInputException`, `ResourceNotFoundException` or `OAuthProviderException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/codebuild-2016-10-06/UpdateWebhook)
"""
@inline update_webhook(aws::AWSConfig=default_aws_config(); args...) = update_webhook(aws, args)

@inline update_webhook(aws::AWSConfig, args) = AWSCore.Services.codebuild(aws, "UpdateWebhook", args)

@inline update_webhook(args) = update_webhook(default_aws_config(), args)

end # module CodeBuild

#==============================================================================#
# End of file
#==============================================================================#


text:
using WolframLinearAlgebra
using Test

@testset "WolframLinearAlgebra.jl" begin
    # Write your own tests here.
end

ext: jl


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

mutable struct IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet <: SwaggerModel
    maxUnavailable::Any # spec type: Union{ Nothing, IoK8sApimachineryPkgUtilIntstrIntOrString } # spec name: maxUnavailable

    function IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet(;maxUnavailable=nothing)
        o = new()
        validate_property(IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet, Symbol("maxUnavailable"), maxUnavailable)
        setfield!(o, Symbol("maxUnavailable"), maxUnavailable)
        o
    end
end # type IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet

const _property_map_IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet = Dict{Symbol,Symbol}(Symbol("maxUnavailable")=>Symbol("maxUnavailable"))
const _property_types_IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet = Dict{Symbol,String}(Symbol("maxUnavailable")=>"IoK8sApimachineryPkgUtilIntstrIntOrString")
Base.propertynames(::Type{ IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet }) = collect(keys(_property_map_IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet))
Swagger.property_type(::Type{ IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet }, name::Symbol) = Union{Nothing,eval(Meta.parse(_property_types_IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet[name]))}
Swagger.field_name(::Type{ IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet }, property_name::Symbol) =  _property_map_IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet[property_name]

function check_required(o::IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet)
    true
end

function validate_property(::Type{ IoK8sApiExtensionsV1beta1RollingUpdateDaemonSet }, name::Symbol, val)
end


text:
# Bogumił Kamiński, 2021

# Codes for chapter 4

# Code for listing 4.1

aq = [10.0   8.04  10.0  9.14  10.0   7.46   8.0   6.58
       8.0   6.95   8.0  8.14   8.0   6.77   8.0   5.76
      13.0   7.58  13.0  8.74  13.0  12.74   8.0   7.71
       9.0   8.81   9.0  8.77   9.0   7.11   8.0   8.84
      11.0   8.33  11.0  9.26  11.0   7.81   8.0   8.47
      14.0   9.96  14.0  8.1   14.0   8.84   8.0   7.04
       6.0   7.24   6.0  6.13   6.0   6.08   8.0   5.25
       4.0   4.26   4.0  3.1    4.0   5.39  19.0  12.50
      12.0  10.84  12.0  9.13  12.0   8.15   8.0   5.56
       7.0   4.82   7.0  7.26   7.0   6.42   8.0   7.91
       5.0   5.68   5.0  4.74   5.0   5.73   8.0   6.89]

# Code for checking size of a matrix

size(aq)
size(aq, 1)
size(aq, 2)

# Code comparing tuple to a vector

v = [1, 2, 3]
t = (1, 2, 3)
v[1]
t[1]
v[1] = 10
v
t[1] = 10

# Code for figure 4.2

using BenchmarkTools
@benchmark (1, 2, 3)
@benchmark [1, 2, 3]

# Code comparing vector and tuple construction

[1, 2.0]
(1, 2.0)

# Code for section 4.1.2

using Statistics
mean(aq; dims=1)
std(aq; dims=1)

map(mean, eachcol(aq))
map(std, eachcol(aq))

map(eachcol(aq)) do col
    mean(col)
end

[mean(col) for col in eachcol(aq)]
[std(col) for col in eachcol(aq)]

x = (-2, -1, 0, 1, 2)
[abs(v) for v in x]
map(abs, x)

# Code for section 4.1.3

[mean(aq[:, j]) for j in axes(aq, 2)]
[std(aq[:, j]) for j in axes(aq, 2)]

axes(aq, 2)

# - change to help mode by pressing `?` key
# - type "Base.OneTo" and press Enter

[mean(view(aq, :, j)) for j in axes(aq, 2)]
[std(@view aq[:, j]) for j in axes(aq, 2)]

# Code for section 4.1.4

using BenchmarkTools
x = ones(10^7, 10)
@btime [mean(@view $x[:, j]) for j in axes($x, 2)];
@btime [mean($x[:, j]) for j in axes($x, 2)];
@btime mean($x, dims=1);

# Code for section 4.1.5

[cor(aq[:, i], aq[:, i+1]) for i in 1:2:7]
collect(1:2:7)

# Code for section 4.1.6

y = aq[:, 2]
X = [ones(11) aq[:, 1]]
X \ y
[[ones(11) aq[:, i]] \ aq[:, i+1] for i in 1:2:7]

function R²(x, y)
    X = [ones(11) x]
    model = X \ y
    prediction = X * model
    error = y - prediction
    SS_res = sum(v -> v ^ 2, error)
    mean_y = mean(y)
    SS_tot = sum(v -> (v - mean_y) ^ 2, y)
    return 1 - SS_res / SS_tot
end
[R²(aq[:, i], aq[:, i+1]) for i in 1:2:7]

# - change to help mode by pressing `?` key
# - type (or copy-paste) "²" and press Enter

# Code for section 4.1.7

using Plots
scatter(aq[:, 1], aq[:, 2]; legend=false)

plot(scatter(aq[:, 1], aq[:, 2]; legend=false),
     scatter(aq[:, 3], aq[:, 4]; legend=false),
     scatter(aq[:, 5], aq[:, 6]; legend=false),
     scatter(aq[:, 7], aq[:, 8]; legend=false))

plot([scatter(aq[:, i], aq[:, i+1]; legend=false)
      for i in 1:2:7]...)

# Code for section 4.2

two_standard = Dict{Int, Int}()
for i in [1, 2, 3, 4, 5, 6]
    for j in [1, 2, 3, 4, 5, 6]
        s = i + j
        if haskey(two_standard, s)
            two_standard[s] += 1
        else
            two_standard[s] = 1
        end
    end
end
two_standard

keys(two_standard)
values(two_standard)

using Plots
scatter(collect(keys(two_standard)), collect(values(two_standard));
        legend=false, xaxis=2:12)

all_dice = [[1, x2, x3, x4, x5, x6]
            for x2 in 2:11
            for x3 in x2:11
            for x4 in x3:11
            for x5 in x4:11
            for x6 in x5:11]

for d1 in all_dice, d2 in all_dice
    test = Dict{Int, Int}()
    for i in d1, j in d2
        s = i + j
        if haskey(test, s)
            test[s] += 1
        else
            test[s] = 1
        end
    end
    if test == two_standard
        println(d1, " ", d2)
    end
end

# Code for section 4.3

aq = [10.0   8.04  10.0  9.14  10.0   7.46   8.0   6.58
       8.0   6.95   8.0  8.14   8.0   6.77   8.0   5.76
      13.0   7.58  13.0  8.74  13.0  12.74   8.0   7.71
       9.0   8.81   9.0  8.77   9.0   7.11   8.0   8.84
      11.0   8.33  11.0  9.26  11.0   7.81   8.0   8.47
      14.0   9.96  14.0  8.1   14.0   8.84   8.0   7.04
       6.0   7.24   6.0  6.13   6.0   6.08   8.0   5.25
       4.0   4.26   4.0  3.1    4.0   5.39  19.0  12.50
      12.0  10.84  12.0  9.13  12.0   8.15   8.0   5.56
       7.0   4.82   7.0  7.26   7.0   6.42   8.0   7.91
       5.0   5.68   5.0  4.74   5.0   5.73   8.0   6.89]

dataset1 = (x=aq[:, 1], y=aq[:, 2])

dataset1[1]
dataset1.x

# Code for listing 4.2

data = (set1=(x=aq[:, 1], y=aq[:, 2]),
        set2=(x=aq[:, 3], y=aq[:, 4]),
        set3=(x=aq[:, 5], y=aq[:, 6]),
        set4=(x=aq[:, 7], y=aq[:, 8]))

# Code for section 4.3.2

using Statistics
map(s -> mean(s.x), data)

map(s -> cor(s.x, s.y), data)

using GLM
model = lm(@formula(y ~ x), data.set1)

r2(model)

# Code for section 4.3.3

model.mm

x = [3, 1, 3, 2]
unique(x)
x
unique!(x)
x

empty_field!(nt, i) = empty!(nt[i])
nt = (dict = Dict("a" => 1, "b" => 2), int=10)
empty_field!(nt, 1)
nt

max_stars_repo_name: bkamins/JuliaForDataAnalysis

max_issues_repo_name: bkamins/JuliaForDataAnalysis

max_forks_repo_name: bkamins/JuliaForDataAnalysis


text:
"""

"""

using DifferentialEquations
using FindSteadyStates
using Plots
using ModelingToolkit
using LabelledArrays
using Parameters
## Build model
function rober(du, u, p, t)
    y1, y2, y3 = u
    k1, k2, k3 = p

    du[1] = -k1*y1 + k3*y2*y3
    du[2] = k1*y1 - k2*y2^2. - k3*y2*y3
    du[3] = k2*y2^2.

end

function rober_jac(J,u,p,t)
    y₁,y₂,y₃ = u
    k₁,k₂,k₃ = p
    J[1,1] = k₁ * -1
    J[2,1] = k₁
    J[3,1] = 0
    J[1,2] = y₃ * k₃
    J[2,2] = y₂ * k₂ * -2 + y₃ * k₃ * -1
    J[3,2] = y₂ * 2 * k₂
    J[1,3] = k₃ * y₂
    J[2,3] = k₃ * y₂ * -1
    J[3,3] = 0
    nothing
  end

## Solve without jacobian
prob = ODEProblem(rober,[1.0,0.0,0.0],(0.0,1e5),(0.04,3e7,1e4))
sol = solve(prob)

## SOlve with jacobian
de = modelingtoolkitize(prob)

jac = eval(ModelingToolkit.generate_jacobian(de)[2])

f = ODEFunction(rober, jac=jac)
prob_jac = ODEProblem(f,[1.0,0.0,0.0],(0.0,1e5),(0.04,3e7,1e4))

@show prob_jac

sol = solve(prob_jac)

@show rober_jac(zeros(3,3), [0.0184367966813563, 7.51141018910664e-8, 0.9815631282045398],(0.04,3.,10.),(0.0,10.))

jac(zeros(3,3),[0.0184367966813563, 7.51141018910664e-8, 0.9815631282045398],(0.0,1e5),(0.04,0.,0.) )
## Plotting
#plot(sol,tspan=(1e-2,1e5),xscale=:log10)

##

using ForwardDiff
using LinearAlgebra

function d(x)
    return -exp.(x)
end

jac = ForwardDiff.jacobian(d, [0.5])

eigvals(jac)

##

@with_kw struct input_func
    func
    p
end

function (self::input_func)(x)
    return self.func(x, x, self.p, (0.0,1.0))
end

function get_jac(de_func, u)
    dj = input_func(de_func.func, de_func.p)
    return ForwardDiff.jacobian(dj, convert(Vector,u))
end

function get_jac2(de_func, u)

    return ForwardDiff.jacobian!(u->de_func(u,u,de_func.p, (0.0,1.0)), u)
end

function bistable_ode!(du, u, p ,t)
	s1, s2 = u
	K1, K2, k1, k2, k3, k4, n1 , n2  = p
	du[1] = k1 / (1 + (s2/K2)^n1) - k3*s1
	du[2] = k2/  (1 + (s1/K1)^n2) - k4*s2
end

p_ = convert(Vector, LVector(K1=1., K2=1., k1=20., k2=20., k3=5., k4=5., n1= 4., n2=4.))

u_1 = convert(Vector, LVector(s1=3., s2=1.) )
u_2 = convert(Vector, LVector(s1=1., s2=3.) )

dss = DEsteady(func=bistable_ode!, u0=u_1, p=p_, method=Tsit5())

sol = solve(dss)

get_jac2(dss, sol.u)

##

function bistable_ode!(du, u, p ,t)
	s1, s2 = u.s1, u.s2
	K1, K2, k1, k2, k3, k4, n1 , n2  = p.K1, p.K2, p.k1, p.k2, p.k3, p.k4, p.n1 , p.n2
	du[1] = k1 / (1 + (s2/K2)^n1) - k3*s1
	du[2] = k2/  (1 + (s1/K1)^n2) - k4*s2
end

p_ = LVector(K1=1., K2=1., k1=20., k2=20., k3=5., k4=5., n1= 4., n2=4.)

u_1 = LVector(s1=3., s2=1.)
u_2 = LVector(s1=1., s2=3.)

##

function bistable_ode!(du, u, p ,t)
	s1, s2 = u
	K1, K2, k1, k2, k3, k4, n1 , n2  = p
	du[1] = k1 / (1 + (s2/K2)^n1) - k3*s1
	du[2] = k2/  (1 + (s1/K1)^n2) - k4*s2
end

p_ = convert(Vector, LVector(K1=1., K2=1., k1=20., k2=20., k3=5., k4=5., n1= 4., n2=4.))

u_1 = convert(Vector, LVector(s1=3., s2=1.) )
u_2 = convert(Vector, LVector(s1=1., s2=3.) )

prob = SteadyStateProblem(bistable_ode!, u_1, p_)
de = modelingtoolkitize(prob)
jac = eval(ModelingToolkit.generate_jacobian(de)[2])
f = ODEFunction(bistable_ode!, jac=jac)
prob_jac_ = SteadyStateProblem(bistable_ode!, u_1 ,p_)

sol = solve(prob)

##
prob = SteadyStateProblem(bistable_ode!, [1.2,1.2], p_)
sol = solve(prob, SSRootfind())
jac_init = zeros(2,2 )
jac(jac_init, sol.u, p_, (1.0,23.5))

@show jac_init
@show eigvals(jac_init)


text:
doc"""
    Cauchy(μ, σ)

The *Cauchy distribution* with location `μ` and scale `σ` has probability density function

$f(x; \mu, \sigma) = \frac{1}{\pi \sigma \left(1 + \left(\frac{x - \mu}{\sigma} \right)^2 \right)}$

```julia
Cauchy()         # Standard Cauchy distribution, i.e. Cauchy(0.0, 1.0)
Cauchy(u)        # Cauchy distribution with location u and unit scale, i.e. Cauchy(u, 1.0)
Cauchy(u, b)     # Cauchy distribution with location u and scale b

params(d)        # Get the parameters, i.e. (u, b)
location(d)      # Get the location parameter, i.e. u
scale(d)         # Get the scale parameter, i.e. b
```

External links

* [Cauchy distribution on Wikipedia](http://en.wikipedia.org/wiki/Cauchy_distribution)

"""
immutable Cauchy <: ContinuousUnivariateDistribution
    μ::Float64
    σ::Float64

    Cauchy(μ::Real, σ::Real) = (@check_args(Cauchy, σ > zero(σ)); new(μ, σ))
    Cauchy(μ::Real) = new(μ, 1.0)
    Cauchy() = new(0.0, 1.0)
end

@distr_support Cauchy -Inf Inf

#### Parameters

location(d::Cauchy) = d.μ
scale(d::Cauchy) = d.σ

params(d::Cauchy) = (d.μ, d.σ)

#### Statistics

mean(d::Cauchy) = NaN
median(d::Cauchy) = d.μ
mode(d::Cauchy) = d.μ

var(d::Cauchy) = NaN
skewness(d::Cauchy) = NaN
kurtosis(d::Cauchy) = NaN

entropy(d::Cauchy) = log4π + log(d.σ)

#### Functions

zval(d::Cauchy, x::Float64) = (x - d.μ) / d.σ
xval(d::Cauchy, z::Float64) = d.μ + z * d.σ

pdf(d::Cauchy, x::Float64) = 1.0 / (π * scale(d) * (1.0 + zval(d, x)^2))
logpdf(d::Cauchy, x::Float64) = - (log1psq(zval(d, x)) + logπ + log(d.σ))

function cdf(d::Cauchy, x::Float64)
    μ, σ = params(d)
    invπ * atan2(x - μ, σ) + 0.5
end

function ccdf(d::Cauchy, x::Float64)
    μ, σ = params(d)
    invπ * atan2(μ - x, σ) + 0.5
end

function quantile(d::Cauchy, p::Float64)
    μ, σ = params(d)
    μ + σ * tan(π * (p - 0.5))
end

function cquantile(d::Cauchy, p::Float64)
    μ, σ = params(d)
    μ + σ * tan(π * (0.5 - p))
end

mgf(d::Cauchy, t::Real) = t == zero(t) ? 1.0 : NaN
cf(d::Cauchy, t::Real) = exp(im * (t * d.μ) - d.σ * abs(t))

#### Fitting

# Note: this is not a Maximum Likelihood estimator
function fit{T<:Real}(::Type{Cauchy}, x::AbstractArray{T})
    l, m, u = quantile(x, [0.25, 0.5, 0.75])
    Cauchy(m, (u - l) / 2.0)
end


text:
module BenchDistance
using BenchmarkTools
using ParallelKMeans
using Distances
using Random

suite = BenchmarkGroup()

Random.seed!(2020)
X = rand(100_000, 3)
centroids = rand(2, 3)
d = rand(100_000, 2)
suite["100kx3"] = @benchmarkable ParallelKMeans.pairwise!($d, $X, $centroids)

X = rand(100_000, 10)
centroids = rand(2, 10)
d = rand(100_000, 2)
suite["100kx10"] = @benchmarkable ParallelKMeans.pairwise!($d, $X, $centroids)

# for reference
metric = SqEuclidean()
suite["100kx10_distances"] = @benchmarkable Distances.pairwise!($d, $metric, $X, $centroids, dims = 1)

end # module

BenchDistance.suite


text:
##################################################
############### LOAD DATA ########################
##################################################

include(joinpath(dirname(@__FILE__), "data_tests/test01.jl"))
omib_sys_file = System(PowerModelsData(omib_file_dir), runchecks = false)

##################################################
############### SOLVE PROBLEM ####################
##################################################
#Define Fault: Change of YBus
Ybus_change = NetworkSwitch(
    1.0, #change at t = 1.0
    Ybus_fault,
) #New YBus

@testset "Make Simulation" begin
    path1 = (joinpath(pwd(), "test-Base-1"))
    !isdir(path1) && mkdir(path1)
    try
        #Define Simulation Problem
        sim = Simulation(
            ImplicitModel,
            omib_sys, #system
            path1,
            (0.0, 30.0), #time span
            Ybus_change;
            system_to_file = true,
        )
        @test sim.status == PSID.BUILT
        o_system = System(joinpath(path1, "input_system.json"))
        for b in get_components(Bus, o_system)
            b_sys = get_component(Bus, omib_sys, get_name(b))
            b_file = get_component(Bus, omib_sys_file, get_name(b))
            @test get_angle(b) == get_angle(b_sys)
            @test get_angle(b) == get_angle(b_file)
        end

    finally
        @info("removing test files")
        rm(path1, force = true, recursive = true)
    end

    path2 = (joinpath(pwd(), "test-Base-2"))
    !isdir(path2) && mkdir(path2)
    try
        #Define Simulation Problem
        sim = Simulation!(
            ImplicitModel,
            omib_sys, #system
            path2,
            (0.0, 30.0), #time span
            Ybus_change;
            system_to_file = true,
        )
        @test sim.status == PSID.BUILT
        m_system = System(joinpath(path2, "initialized_system.json"))
        for b in get_components(Bus, m_system)
            b_sys = get_component(Bus, omib_sys, get_name(b))
            b_file = get_component(Bus, omib_sys_file, get_name(b))
            @test get_angle(b) == get_angle(b_sys)
            if get_bustype(b) == PSY.BusTypes.REF
                @test get_angle(b) == get_angle(b_file)
            else
                @test get_angle(b) != get_angle(b_file)
            end
        end

    finally
        @info("removing test files")
        rm(path2, force = true, recursive = true)
    end
end

@testset "Hybrid Line Indexing" begin
    ## Create threebus system with more dyn lines ##
    three_bus_file_dir = joinpath(dirname(@__FILE__), "data_tests/ThreeBusInverter.raw")
    threebus_sys_dyns = System(three_bus_file_dir, runchecks = false)
    add_source_to_ref(threebus_sys_dyns)

    dyn_branch12 =
        DynamicBranch(get_component(Branch, threebus_sys_dyns, "BUS 1-BUS 2-i_2"))
    dyn_branch23 =
        DynamicBranch(get_component(Branch, threebus_sys_dyns, "BUS 2-BUS 3-i_3"))

    add_component!(threebus_sys_dyns, dyn_branch12)
    add_component!(threebus_sys_dyns, dyn_branch23)

    # Attach dyn devices
    for g in get_components(Generator, threebus_sys_dyns)
        if get_number(get_bus(g)) == 102
            case_gen = dyn_gen_second_order(g)
            add_component!(threebus_sys_dyns, case_gen, g)
        elseif get_number(get_bus(g)) == 103
            case_inv = inv_case78(g)
            add_component!(threebus_sys_dyns, case_inv, g)
        end
    end

    # Tests for all Dynamic Lines
    sim = Simulation(ImplicitModel, threebus_sys_dyns, pwd(), (0.0, 10.0))
    @test sim.status == PSID.BUILT
    sim_inputs = sim.simulation_inputs
    dae_vector = PSID.get_DAE_vector(sim_inputs)
    @test all(dae_vector)
    total_shunts = PSID.get_total_shunts(sim_inputs)
    for v in LinearAlgebra.diag(total_shunts)
        @test imag(v) > 0
    end

    for entry in LinearAlgebra.diag(sim_inputs.mass_matrix)
        @test entry > 0
    end
    voltage_buses_ix = PSID.get_voltage_buses_ix(sim_inputs)
    @test length(voltage_buses_ix) == 3

    # Tests for dynamic lines with b = 0
    set_b!(dyn_branch12, (from = 0.0, to = 0.0))
    set_b!(dyn_branch23, (from = 0.0, to = 0.0))
    sim = Simulation(ImplicitModel, threebus_sys_dyns, pwd(), (0.0, 10.0))
    @test sim.status == PSID.BUILT
    sim_inputs = sim.simulation_inputs
    dae_vector = PSID.get_DAE_vector(sim_inputs)
    @test sum(.!dae_vector) == 6
    for (ix, entry) in enumerate(dae_vector)
        if !entry
            @test LinearAlgebra.diag(sim_inputs.mass_matrix)[ix] == 0
        elseif entry
            @test LinearAlgebra.diag(sim_inputs.mass_matrix)[ix] == 1
        else
            @test false
        end
    end

    total_shunts = PSID.get_total_shunts(sim_inputs)
    @test sum(LinearAlgebra.diag(total_shunts)) == 0.0
    voltage_buses_ix = PSID.get_voltage_buses_ix(sim_inputs)
    @test isempty(voltage_buses_ix)
end


text:
module TestGrouping

using Test
using DataFrames
using DataFramesMeta
using Statistics
using Tables

d = DataFrame(n = 1:20, x = [3, 3, 3, 3, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 3, 1, 1, 2])
g = groupby(d, :x, sort=true)

@test  @where(d, :x .== 3) == DataFramesMeta.where(d, x -> x.x .== 3)
@test  DataFrame(@where(g, length(:x) > 5)) == DataFrame(DataFramesMeta.where(g, x -> length(x.x) > 5))
@test  DataFrame(@where(g, length(:x) > 5))[!, :n][1:3] == [5, 6, 7]

@test  DataFrame(DataFramesMeta.orderby(g, x -> mean(x.n))) == DataFrame(@orderby(g, mean(:n)))

@test  (@transform(g, y = :n .- median(:n)))[1,:y] == -5.0

d = DataFrame(n = 1:20, x = [3, 3, 3, 3, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 3, 1, 1, 2])
g = groupby(d, :x, sort=true)
@test @based_on(g, nsum = sum(:n)).nsum == [99, 84, 27]

# Transform tests
d = DataFrame(a = [1,1,1,2,2,3,3,1],
              b = Any[1,2,3,missing,missing,6.0,5.0,4],
              c = CategoricalArray([1,2,3,1,2,3,1,2]))
g = groupby(d, :a)
## Scalar output
# Type promotion Int -> Float
t = @transform(g, t = :b[1]).t
@test isequal(t, [1.0, 1.0, 1.0, 1.0, missing, missing, 6.0, 6.0]) &&
      t isa Vector{Union{Float64, Missing}}
# Type promotion Number -> Any
t = @transform(g, t = isequal(:b[1], 1) ? :b[1] : "a").t
@test isequal(t, [1, 1, 1, 1, "a", "a", "a", "a"]) &&
      t isa Vector{Any}
## Vector output
# Normal use
t = @transform(g, t = :b .- mean(:b)).t
@test isequal(t, [-1.5, -0.5, 0.5, 1.5, missing, missing, 0.5, -0.5]) &&
      t isa Vector{Union{Float64, Missing}}
# Type promotion
t = @transform(g, t = isequal(:b[1], 1) ? fill(1, length(:b)) : fill(2.0, length(:b))).t
@test isequal(t, [1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0]) &&
      t isa Vector{Float64}
# Vectors whose eltypes promote to any
t = @transform(g, t = isequal(:b[1], 1) ? :b : fill("a", length(:b))).t
@test isequal(t, [1, 2, 3, 4, "a", "a", "a", "a"]) &&
      t isa Vector{Any}
# Categorical Array
# Scalar
t = @transform(g, t = :c[1]).t
@test isequal(t, [1, 1, 1, 1, 1, 1, 3, 3]) &&
      t isa CategoricalVector{Int}
# Vector
t = @transform(g, t = :c).t
@test isequal(t, [1, 2, 3, 2, 1, 2, 3, 1]) &&
      t isa CategoricalVector{Int}
end # module


text:
"""
    MatrixNormal(M, U, V)
```julia
M::AbstractMatrix  n x p mean
U::AbstractPDMat   n x n row covariance
V::AbstractPDMat   p x p column covariance
```
The [matrix normal distribution](https://en.wikipedia.org/wiki/Matrix_normal_distribution)
generalizes the multivariate normal distribution to ``n\\times p`` real matrices ``\\mathbf{X}``.
If ``\\mathbf{X}\\sim \\textrm{MN}_{n,p}(\\mathbf{M}, \\mathbf{U}, \\mathbf{V})``, then its
probability density function is

```math
f(\\mathbf{X};\\mathbf{M}, \\mathbf{U}, \\mathbf{V}) = \\frac{\\exp\\left( -\\frac{1}{2} \\, \\mathrm{tr}\\left[ \\mathbf{V}^{-1} (\\mathbf{X} - \\mathbf{M})^{\\rm{T}} \\mathbf{U}^{-1} (\\mathbf{X} - \\mathbf{M}) \\right] \\right)}{(2\\pi)^{np/2} |\\mathbf{V}|^{n/2} |\\mathbf{U}|^{p/2}}.
```

``\\mathbf{X}\\sim \\textrm{MN}_{n,p}(\\mathbf{M},\\mathbf{U},\\mathbf{V})``
if and only if ``\\text{vec}(\\mathbf{X})\\sim \\textrm{N}(\\text{vec}(\\mathbf{M}),\\mathbf{V}\\otimes\\mathbf{U})``.
"""
struct MatrixNormal{T <: Real, TM <: AbstractMatrix, TU <: AbstractPDMat, TV <: AbstractPDMat} <: ContinuousMatrixDistribution
    M::TM
    U::TU
    V::TV
    logc0::T
end

#  -----------------------------------------------------------------------------
#  Constructors
#  -----------------------------------------------------------------------------

function MatrixNormal(M::AbstractMatrix{T}, U::AbstractPDMat{T}, V::AbstractPDMat{T}) where T <: Real
    n, p = size(M)
    n == dim(U) || throw(ArgumentError("Number of rows of M must equal dim of U."))
    p == dim(V) || throw(ArgumentError("Number of columns of M must equal dim of V."))
    logc0 = matrixnormal_logc0(U, V)
    R = Base.promote_eltype(T, logc0)
    prom_M = convert(AbstractArray{R}, M)
    prom_U = convert(AbstractArray{R}, U)
    prom_V = convert(AbstractArray{R}, V)
    MatrixNormal{R, typeof(prom_M), typeof(prom_U), typeof(prom_V)}(prom_M, prom_U, prom_V, R(logc0))
end

function MatrixNormal(M::AbstractMatrix, U::AbstractPDMat, V::AbstractPDMat)
    T = Base.promote_eltype(M, U, V)
    MatrixNormal(convert(AbstractArray{T}, M), convert(AbstractArray{T}, U), convert(AbstractArray{T}, V))
end

MatrixNormal(M::AbstractMatrix, U::Union{AbstractMatrix, LinearAlgebra.Cholesky}, V::Union{AbstractMatrix, LinearAlgebra.Cholesky}) = MatrixNormal(M, PDMat(U), PDMat(V))
MatrixNormal(M::AbstractMatrix, U::Union{AbstractMatrix, LinearAlgebra.Cholesky}, V::AbstractPDMat) = MatrixNormal(M, PDMat(U), V)
MatrixNormal(M::AbstractMatrix, U::AbstractPDMat, V::Union{AbstractMatrix, LinearAlgebra.Cholesky}) = MatrixNormal(M, U, PDMat(V))

MatrixNormal(m::Int, n::Int) = MatrixNormal(zeros(m, n), Matrix(1.0I, m, m), Matrix(1.0I, n, n))

#  -----------------------------------------------------------------------------
#  REPL display
#  -----------------------------------------------------------------------------

show(io::IO, d::MatrixNormal) = show_multline(io, d, [(:M, d.M), (:U, Matrix(d.U)), (:V, Matrix(d.V))])

#  -----------------------------------------------------------------------------
#  Conversion
#  -----------------------------------------------------------------------------

function convert(::Type{MatrixNormal{T}}, d::MatrixNormal) where T <: Real
    MM = convert(AbstractArray{T}, d.M)
    UU = convert(AbstractArray{T}, d.U)
    VV = convert(AbstractArray{T}, d.V)
    MatrixNormal{T, typeof(MM), typeof(UU), typeof(VV)}(MM, UU, VV, T(d.logc0))
end
Base.convert(::Type{MatrixNormal{T}}, d::MatrixNormal{T}) where {T<:Real} = d

function convert(::Type{MatrixNormal{T}}, M::AbstractMatrix, U::AbstractPDMat, V::AbstractPDMat, logc0) where T <: Real
    MM = convert(AbstractArray{T}, M)
    UU = convert(AbstractArray{T}, U)
    VV = convert(AbstractArray{T}, V)
    MatrixNormal{T, typeof(MM), typeof(UU), typeof(VV)}(MM, UU, VV, T(logc0))
end

#  -----------------------------------------------------------------------------
#  Properties
#  -----------------------------------------------------------------------------

size(d::MatrixNormal) = size(d.M)

rank(d::MatrixNormal) = minimum( size(d) )

insupport(d::MatrixNormal, X::AbstractMatrix) = isreal(X) && size(X) == size(d)

mean(d::MatrixNormal) = d.M

mode(d::MatrixNormal) = d.M

cov(d::MatrixNormal) = Matrix(kron(d.V, d.U))

cov(d::MatrixNormal, ::Val{false}) = ((n, p) = size(d); reshape(cov(d), n, p, n, p))

var(d::MatrixNormal) = reshape(diag(cov(d)), size(d))

params(d::MatrixNormal) = (d.M, d.U, d.V)

@inline partype(d::MatrixNormal{T}) where {T<:Real} = T

#  -----------------------------------------------------------------------------
#  Evaluation
#  -----------------------------------------------------------------------------

function matrixnormal_logc0(U::AbstractPDMat, V::AbstractPDMat)
    n = dim(U)
    p = dim(V)
    -(n * p / 2) * (logtwo + logπ) - (n / 2) * logdet(V) - (p / 2) * logdet(U)
end

function logkernel(d::MatrixNormal, X::AbstractMatrix)
    A  = X - d.M
    -0.5 * tr( (d.V \ A') * (d.U \ A) )
end

#  -----------------------------------------------------------------------------
#  Sampling
#  -----------------------------------------------------------------------------

#  https://en.wikipedia.org/wiki/Matrix_normal_distribution#Drawing_values_from_the_distribution

function _rand!(rng::AbstractRNG, d::MatrixNormal, Y::AbstractMatrix)
    n, p = size(d)
    X = randn(rng, n, p)
    A = cholesky(d.U).L
    B = cholesky(d.V).U
    Y .= d.M .+ A * X * B
end

#  -----------------------------------------------------------------------------
#  Test utils
#  -----------------------------------------------------------------------------

function _univariate(d::MatrixNormal)
    check_univariate(d)
    M, U, V = params(d)
    μ = M[1]
    σ = sqrt( Matrix(U)[1] * Matrix(V)[1] )
    return Normal(μ, σ)
end

function _multivariate(d::MatrixNormal)
    n, p = size(d)
    all([n, p] .> 1) && throw(ArgumentError("Row or col dim of `MatrixNormal` must be 1 to coerce to `MvNormal`"))
    return vec(d)
end

function _rand_params(::Type{MatrixNormal}, elty, n::Int, p::Int)
    M = randn(elty, n, p)
    U = (X = 2 .* rand(elty, n, n) .- 1; X * X')
    V = (Y = 2 .* rand(elty, p, p) .- 1; Y * Y')
    return M, U, V
end


text:
using Integrals
const P = Integrals
using Test
using StaticArrays
using LinearAlgebra
using Random
using Setfield
using Cuba: vegas
using HCubature

struct Constant{T} <: Function
    value::T
end

(f::Constant)(_) = f.value

@test integral === ∫

function isconsistent(truth, est; nstd=6, kw_approx...)
    val = est.value
    Δ = nstd * est.std
    if ≈(val, truth; kw_approx...)
        true
    elseif (truth - Δ <= val <= truth + Δ)
        true
    else
        @show truth
        @show est
        @show kw_approx
        false
    end
end

ALGS = [Vegas(), MCVanilla(), CubaAlg(vegas), HCubatureAlg()]

@testset "RNG Reproducibility" begin
    for alg in [Vegas(), MCVanilla()]
        @set! alg.rng = MersenneTwister(1)
        res1 = ∫(cos, (0,1), alg)
        @set! alg.rng = MersenneTwister(1)
        res2 = ∫(cos, (0,1), alg)
        @test res1 === res2
        res3 = ∫(cos, (0,1), alg)
        @test !(res3 === res2)
    end
end

@testset "Domain" begin
    dom = Domain((1f0, 2f0))
    @test P.pointtype(typeof(dom)) === SVector{1, Float32}
    @test P.volume(dom) === 1f0
end

@testset "zero function" begin
    f = Constant(0.)
    for alg in ALGS
        for dim in 1:4
            lower = @SVector randn(dim)
            upper = lower + @SVector rand(dim)
            dom = Domain(lower, upper)
            est = ∫(f, dom, alg)
            @test est.value ≈ 0 atol=100eps(Float64)
        end
    end
end

@testset "exotic types $(typeof(alg))" for alg in [
        MCVanilla(10),
        Vegas(100),
        CubaAlg(vegas),
       ]
    est = ∫(identity, (0f0, 1f0), alg)
    @test typeof(est.value) === Float32
    @test typeof(est.std) === Float32

    est = ∫(_ -> true, (0f0, 1f0), alg)
    @test typeof(est.value) === Float64
    @test typeof(est.std) === Float64

    est = ∫(identity, (0, 1), alg)
    @test typeof(est.value) === Float64
    @test typeof(est.std) === Float64

    est = ∫(identity, (big"0", big"1"), alg)
    @test typeof(est.value) === BigFloat
    @test typeof(est.std) === BigFloat

    v = @SVector[1.,2.]
    est = ∫(_ -> v, (0,1), alg)
    @test typeof(est.value) === typeof(v)
    @test typeof(est.std)   === typeof(est.value)
end

@testset "Inferred $(typeof(alg))" for alg in [MCVanilla(), Vegas(),
                                               CubaAlg(vegas), HCubatureAlg()]
    f_scalar = x -> x[1]^2
    f_vec    = x -> @SVector[1.,2,3]
    dom = Domain((-pi, 1))

    @inferred ∫(f_scalar, dom, alg)
    # @inferred ∫(f_vec, dom, alg)
end

@testset "constant $(typeof(alg))" for alg in ALGS
    for dim in 1:4
        for _ in 1:3
            lower = @SVector randn(dim)
            upper = lower + @SVector rand(dim)
            val = randn()
            f = Constant(val)
            dom = Domain(lower, upper)
            est = ∫(f, dom, alg)
            @test !isnan(est.value)
            vol = prod(upper .- lower)
            truth = val * vol
            @test isconsistent(truth, est)
            @test est.std < 1e-3
        end
    end
end

@testset "∫x^2" begin
    est_vegas = ∫(x->x^2, (0,1), Vegas(10000))
    @test isconsistent(1/3, est_vegas)
    @test_broken est_vegas.std < 1e-3

    est_vanilla = ∫(x->x^2, (0,1), MCVanilla(1000))
    @test isconsistent(1/3, est_vanilla)
    @test est_vanilla.std < 1e-2
end

@testset "∫(f, (a,b), $(typeof(alg)))" for alg in [
        MCVanilla(10^4),
        Vegas(10^4),
       ]

    funs = [
        (f = x -> x^2, F = x -> x^3/3),
        (f = cos, F = sin),
        let
            a = randn()
            (f = _ -> a, F = x -> a*x)
        end
    ]

    for (f,F) in funs
        for _ in 1:10
            a = 10randn()
            b = a + 10rand()
            est = ∫(f, (a,b), alg)
            truth = F(b) - F(a)
            @test isconsistent(truth, est)
        end
    end
end

@testset "Fubini $(typeof(alg))" for alg in [
    MCVanilla(10^4),
    Vegas(10^4)]
    for _ in 1:10
        a1,a2 = randn(2)
        b1 = a1 + 10rand()
        b2 = a2 + 10rand()
        dom1 = Domain((a1, b1))
        dom2 = Domain((a2, b2))
        dom = Domain(((a1, b1), (a2, b2)))
        f1 = x -> cos(x[1])
        F1 = x -> sin(x[1])
        f2 = x -> x[1]^2
        F2 = x -> x[1]^3/3
        f  = v -> f1(v[1]) * f2(v[2])
        est1 = ∫(f1, dom1, alg)
        est2 = ∫(f2, dom2, alg)
        est  = ∫(f , dom , alg)
        @test isconsistent(est1.value*est2.value, est)
    end
end

@testset "Ball $(typeof(alg))" for alg in [
    MCVanilla(10^4),
    Vegas(10^4, rng=MersenneTwister(1))]

    f(x) = norm(x) < 1 ? 1. : 0.
    est = ∫(f, (-2,2), alg)
    @test isconsistent(2,est)

    est = ∫(f, ((-1,1),(-1,1)), alg)
    @test isconsistent(π, est)

    est = ∫(f, ((-1,1),(-1,1),(-1,1)), alg)
    @test isconsistent(4π/3, est)
end

@testset "std bernoulli" begin
    for _ in 1:10
        p = 0.1 + 0.8*rand()
        f = x -> 0 <= x <= p

        neval = 1000
        true_value = p
        true_std = sqrt(p*(1-p)/neval)

        est = ∫(f, (0,1), MCVanilla(neval))
        @test est.std ≈ true_std rtol=0.2
        @test isconsistent(true_value, est)

        est = ∫(f, (0,1), Vegas(neval))
        if est.std < true_std
            @test est.std < true_std
        else
            @test_broken est.std < true_std
        end
        @test isconsistent(true_value, est)
    end
end


text:
module Jedis

export Client, Pipeline, RedisError, get_global_client, set_global_client, get_ssl_config,
       disconnect!, reconnect!, add!, copy, wait_until_subscribed, wait_until_unsubscribed,
       wait_until_channel_unsubscribed, wait_until_pattern_unsubscribed, execute, auth, select,
       ping, flushdb, flushall, quit, set, setnx, get, del, exists, hexists, hkeys, setex,
       expire, ttl, multi, exec, multi_exec, pipeline, hset, hget, hgetall, hmget, hdel, rpush,
       lpush, lpos, lrem, lpop, rpop, blpop, brpop, llen, lrange, publish, subscribe, unsubscribe,
       psubscribe, punsubscribe, incr, incrby, incrbyfloat, hincrby, hincrbyfloat, zincrby, zadd,
       zrange, zrangebyscore, zrem, acquire_lock, release_lock, redis_lock, isredislocked

using Sockets
using MbedTLS
using UUIDs: uuid4
import Base: copy, showerror, get, pipeline

include("exceptions.jl")
include("utilities.jl")
include("client.jl")
include("pipeline.jl")
include("protocol.jl")
include("execute.jl")
include("commands.jl")
include("pubsub.jl")
include("lock.jl")

end # module


text:
function first_derivative(x_vec,y_vec)
    Nx = length(x_vec)
    Ny = length(y_vec)
    if Nx != Ny
        return println("Error: the two input vectors do not have the same size")
    end
    drv = diff(y_vec)./diff(x_vec)
    #drv[end] = (y_vec[end] - y_vec[end-1])/(x_vec[end] - x_vec[end-1])
    return drv
end


text:
require("Codecs")
require("Compose")
require("DataFrames")
require("Distributions")
require("Iterators")
require("JSON")

module Gadfly

using Codecs
using Color
using Compose
using DataFrames
using JSON

import Iterators
import Compose.draw, Compose.hstack, Compose.vstack
import Base.copy, Base.push!, Base.start, Base.next, Base.done, Base.has,
       Base.show, Base.getindex

export Plot, Layer, Scale, Coord, Geom, Guide, Stat, render, plot, layer, @plot, spy

# Re-export some essentials from Compose
export D3, SVG, PNG, PS, PDF, draw, inch, mm, px, pt, color, vstack, hstack

typealias ColorOrNothing Union(ColorValue, Nothing)

element_aesthetics(::Any) = []
default_scales(::Any) = []

abstract Element
abstract ScaleElement       <: Element
abstract CoordinateElement  <: Element
abstract GeometryElement    <: Element
abstract GuideElement       <: Element
abstract StatisticElement   <: Element

include("misc.jl")
include("ticks.jl")
include("color.jl")
include("theme.jl")
include("aesthetics.jl")
include("data.jl")
include("weave.jl")
include("poetry.jl")

# A plot has zero or more layers. Layers have a particular geometry and their
# own data, which is inherited from the plot if not given.
type Layer <: Element
    data_source::Union(AbstractDataFrame, Nothing)
    mapping::Dict
    statistic::StatisticElement
    geom::GeometryElement

    function Layer()
        new(nothing, Dict(), Stat.nil, Geom.nil)
    end

    function Layer(data::Union(Nothing, AbstractDataFrame), mapping::Dict,
                   statistic::StatisticElement, geom::GeometryElement)
        new(data, mapping, statistic, geom)
    end
end

function layer(data::Union(AbstractDataFrame, Nothing),
               statistic::StatisticElement=Stat.nil,
               geom::GeometryElement=Geom.nil;
               mapping...)
    Layer(data, {k => v for (k, v) in mapping}, statistic, geom)
end

function layer(statistic::StatisticElement,
               geom::GeometryElement;
               mapping...)
    layer(nothing, statistic, geom; mapping...)
end

function layer(geom::GeometryElement; mapping...)
    layer(nothing, Stat.nil, geom; mapping...)
end

# A full plot specification.
type Plot
    layers::Vector{Layer}
    data_source::Union(Nothing, AbstractDataFrame)
    data::Data
    scales::Vector{ScaleElement}
    statistics::Vector{StatisticElement}
    coord::CoordinateElement
    guides::Vector{GuideElement}
    theme::Theme
    mapping::Dict

    function Plot()
        new(Layer[], nothing, Data(), ScaleElement[], StatisticElement[],
            Coord.cartesian, GuideElement[], default_theme)
    end
end

function add_plot_element(p::Plot, data::AbstractDataFrame, arg::GeometryElement)
    layer = Layer()
    layer.geom = arg
    push!(p.layers, layer)
end

function add_plot_element(p::Plot, data::AbstractDataFrame, arg::ScaleElement)
    push!(p.scales, arg)
end

function add_plot_element(p::Plot, data::AbstractDataFrame, arg::StatisticElement)
    if isempty(p.layers)
        push!(p.layers, Layer())
    end

    p.layers[end].statistic = arg
end

function add_plot_element(p::Plot, data::AbstractDataFrame, arg::CoordinateElement)
    p.coord = arg
end

function add_plot_element(p::Plot, data::AbstractDataFrame, arg::GuideElement)
    push!(p.guides, arg)
end

function add_plot_element(p::Plot, data::AbstractDataFrame, arg::Layer)
    push!(p.layers, arg)
end

eval_plot_mapping(data::AbstractDataFrame, arg::Symbol) = data[string(arg)]
eval_plot_mapping(data::AbstractDataFrame, arg::String) = data[arg]
eval_plot_mapping(data::AbstractDataFrame, arg::Integer) = data[arg]
eval_plot_mapping(data::AbstractDataFrame, arg::Expr) = with(data, arg)
eval_plot_mapping(data::AbstractDataFrame, arg::AbstractArray) = arg

# Acceptable types of values that can be bound to aesthetics.
typealias AestheticValue Union(Nothing, Symbol, String, Integer, Expr,
                               AbstractArray)

# Create a new plot.
#
# Grammar of graphics style plotting consists of specifying a dataset, one or
# more plot elements (scales, coordinates, geometries, etc), and binding of
# aesthetics to columns or expressions of the dataset.
#
# For example, a simple scatter plot would look something like:
#
#     plot(my_data, Geom.point, x="time", y="price")
#
# Where "time" and "price" are the names of columns in my_data.
#
# Args:
#   data: Data to be bound to aesthetics.
#   mapping: Aesthetics symbols (e.g. :x, :y, :color) mapped to
#            names of columns in the data frame or other expressions.
#   elements: Geometries, statistics, etc.

function plot(data::AbstractDataFrame, elements::Element...; mapping...)
    p = Plot()
    p.mapping = Dict()
    p.data_source = data
    valid_aesthetics = Set(names(Aesthetics)...)
    for (k, v) in mapping
        if !contains(valid_aesthetics, k)
            error("$(k) is not a recognized aesthetic")
        end

        if !(typeof(v) <: AestheticValue)
            error(
            """Aesthetic $(k) is mapped to a value of type $(typeof(v)).
               It must be mapped to a string, symbol, or expression.""")
        end

        setfield(p.data, k, eval_plot_mapping(data, v))
        p.mapping[k] = v
    end

    for element in elements
        add_plot_element(p, data, element)
    end

    p
end

function plot(elements::Element...; mapping...)
    plot(DataFrame(), elements...; mapping...)
end

# The old fashioned (pre named arguments) version of plot.
#
# This version takes an explicit mapping dictionary, mapping aesthetics symbols
# to expressions or columns in the data frame.
#
# Args:
#   data: Data to be bound to aesthetics.
#   mapping: Dictionary of aesthetics symbols (e.g. :x, :y, :color) to
#            names of columns in the data frame or other expressions.
#   elements: Geometries, statistics, etc.
#
# Returns:
#   A Plot object.
#
function plot(data::AbstractDataFrame, mapping::Dict, elements::Element...)
    p = Plot()
    for element in elements
        add_plot_element(p, data, element)
    end

    for (var, value) in mapping
        setfield(p.data, var, eval_plot_mapping(data, value))
    end
    p.mapping = mapping
    p.data_source = data

    p
end

function plot(mapping::Dict, elements::Element...)
    plot(DataFrame, mapping, elements...)
end

# Turn a graph specification into a graphic.
#
# This is where magic happens (sausage is made). Processing all the parts of the
# plot is actually pretty simple. It's made complicated by trying to handle
# defaults. With that aside, plots are made in the following steps.
#
#    I. Apply scales to transform raw data to the form expected by the aesthetic.
#   II. Apply statistics to the scaled data. Statistics are essentially functions
#       that map one or more aesthetics to one or more aesthetics.
#  III. Apply coordinates. Currently all this does is figure out the coordinate
#       system used by the plot panel canvas.
#   IV. Render geometries. This gives us one or more compose forms suitable to be
#       composed with the plot's panel.
#    V. Render guides. Guides are conceptually very similar to geometries but with
#       the ability to be placed outside of the plot panel.
#
#  Finally there is a very important call to layout_guides which puts everything
#  together.
#
# Args:
#   plot: a plot to render.
#
# Returns:
#   A compose Canvas containing the graphic.
#
function render(plot::Plot)
    if isempty(plot.layers)
        layer = Layer()
        layer.geom = Geom.point
        push!(plot.layers, layer)
    end

    # Process layers, filling inheriting mappings or data from the Plot where
    # they are missing.
    datas = Array(Data, length(plot.layers))
    for (i, layer) in enumerate(plot.layers)
        if layer.data_source === nothing && isempty(layer.mapping)
            datas[i] = plot.data
        else
            datas[i] = Data()

            if layer.data_source === nothing
                layer.data_source = plot.data_source
            end

            if isempty(layer.mapping)
                layer.mapping = plot.mapping
            end

            for (k, v) in layer.mapping
                setfield(datas[i], k, eval_plot_mapping(layer.data_source, v))
            end
        end
    end

    # Add default statistics for geometries.
    layer_stats = Array(StatisticElement, length(plot.layers))
    for (i, layer) in enumerate(plot.layers)
        layer_stats[i] = is(layer.statistic, Stat.nil) ?
                            Geom.default_statistic(layer.geom) : layer.statistic
    end

    used_aesthetics = Set{Symbol}()
    for layer in plot.layers
        union!(used_aesthetics, element_aesthetics(layer.geom))
    end

    for stat in layer_stats
        union!(used_aesthetics, element_aesthetics(stat))
    end

    defined_unused_aesthetics = setdiff(Set(keys(plot.mapping)...), used_aesthetics)
    if !isempty(defined_unused_aesthetics)
        warn("The following aesthetics are mapped, but not used by any geometry:\n    ",
             join([string(a) for a in defined_unused_aesthetics], ", "))
    end

    scaled_aesthetics = Set{Symbol}()
    for scale in plot.scales
        union!(scaled_aesthetics, element_aesthetics(scale))
    end

    # Only one scale can be applied to an aesthetic (without getting some weird
    # and incorrect results), so we organize scales into a dict.
    scales = Dict{Symbol, ScaleElement}()
    for scale in plot.scales
        for var in element_aesthetics(scale)
            scales[var] = scale
        end
    end

    unscaled_aesthetics = setdiff(used_aesthetics, scaled_aesthetics)

    # Add default scales for statistics.
    for stat in layer_stats
        for scale in default_scales(stat)
            # Use the statistics default scale only when it covers some
            # aesthetic that is not already scaled.
            scale_aes = Set(element_aesthetics(scale)...)
            if !isempty(intersect(scale_aes, unscaled_aesthetics))
                for var in scale_aes
                    scales[var] = scale
                end
                setdiff!(unscaled_aesthetics, scale_aes)
            end
        end
    end

    # Assign scales to mapped aesthetics first.
    for var in unscaled_aesthetics
        if !haskey(plot.mapping, var)
            continue
        end

        t = classify_data(getfield(plot.data, var))
        if haskey(default_aes_scales[t], var)
            scale = default_aes_scales[t][var]
            scale_aes = Set(element_aesthetics(scale)...)
            for var in scale_aes
                scales[var] = scale
            end
        end
    end

    for var in unscaled_aesthetics
        if haskey(plot.mapping, var) || haskey(scales, var)
            continue
        end

        if haskey(default_aes_scales[:discrete], var)
            scale = default_aes_scales[:discrete][var]
            scale_aes = Set(element_aesthetics(scale)...)
            for var in scale_aes
                scales[var] = scale
            end
        end
    end

    # There can be at most one instance of each guide. This is primarily to
    # prevent default guides being applied over user-supplied guides.
    guides = Dict{Type, GuideElement}()
    for guide in plot.guides
        guides[typeof(guide)] = guide
    end
    guides[Guide.PanelBackground] = Guide.background
    guides[Guide.XTicks] = Guide.x_ticks
    guides[Guide.YTicks] = Guide.y_ticks

    statistics = copy(plot.statistics)
    push!(statistics, Stat.x_ticks)
    push!(statistics, Stat.y_ticks)

    function mapped_and_used(vs)
        any([haskey(plot.mapping, v) && contains(used_aesthetics, v) for v in vs])
    end

    function choose_name(vs)
        for v in vs
            if haskey(plot.mapping, v) && !(typeof(plot.mapping[v]) <: AbstractArray)
                return string(plot.mapping[v])
            end
        end
        string(vs[1])
    end

    if mapped_and_used(Scale.x_vars) && !haskey(guides, Guide.XLabel)
        guides[Guide.XLabel] =  Guide.XLabel(choose_name(Scale.x_vars))
    end

    if mapped_and_used(Scale.y_vars) && !haskey(guides, Guide.YLabel)
        guides[Guide.YLabel] = Guide.YLabel(choose_name(Scale.y_vars))
    end

    # I. Scales
    aess = Scale.apply_scales(Iterators.distinct(values(scales)), datas...)

    # set default labels
    if haskey(plot.mapping, :color)
        aess[1].color_key_title = string(plot.mapping[:color])
    end

    # IIa. Layer-wise statistics
    for (layer_stat, aes) in zip(layer_stats, aess)
        Stat.apply_statistics(StatisticElement[layer_stat], scales, plot.coord, aes)
    end

    # IIb. Plot-wise Statistics
    plot_aes = cat(aess...)
    Stat.apply_statistics(statistics, scales, plot.coord, plot_aes)

    # Add some default guides determined by defined aesthetics
    if !all([aes.color === nothing for aes in [plot_aes, aess...]]) &&
       !haskey(guides, Guide.ColorKey)
        guides[Guide.ColorKey] = Guide.colorkey
    end

    # III. Coordinates
    plot_canvas = Coord.apply_coordinate(plot.coord, plot_aes, aess...)

    # Now that coordinates are set, layer aesthetics inherit plot aesthetics.
    for aes in aess
        inherit!(aes, plot_aes)
    end

    # IV. Geometries
    plot_canvas = compose(plot_canvas,
                          [render(layer.geom, plot.theme, aes)
                           for (layer, aes) in zip(plot.layers, aess)]...)

    # V. Guides
    guide_canvases = {}
    for guide in values(guides)
        append!(guide_canvases, render(guide, plot.theme, aess))
    end

    canvas = Guide.layout_guides(plot_canvas, plot.theme, guide_canvases...)

    # TODO: This is a kludge. Axis labels sometimes extend past the edge of the
    # canvas.
    pad(canvas, 5mm)
end

# A convenience version of Compose.draw that let's you skip the call to render.
draw(backend::Compose.Backend, p::Plot) = draw(backend, render(p))

# Convenience stacking functions
vstack(ps::Plot...) = vstack([render(p) for p in ps]...)
vstack(ps::Vector{Plot}) = vstack([render(p) for p in ps]...)

hstack(ps::Plot...) = hstack([render(p) for p in ps]...)
hstack(ps::Vector{Plot}) = hstack([render(p) for p in ps]...)

# Displaying plots, for interactive use.
#
# This is a show function that, rather than outputing a totally incomprehensible
# representation of the Plot object, renders it, and emits the graphic. (Which
# usually means, shows it in a browser window.)
#
function show(io::IO, p::Plot)
    # TODO: This is stilly kludgy
    if io === STDOUT
        draw(SVG(6inch, 5inch), p)
    else
        print(io, "Plot(...)")
    end
end
# TODO: Find a more elegant way to automatically show plots. This is unexpected
# and gives weave problems.

include("scale.jl")
include("coord.jl")
include("geometry.jl")
include("guide.jl")
include("statistics.jl")

# All aesthetics must have a scale. If none is given, we use a default.
# The default depends on whether the input is discrete or continuous (i.e.,
# PooledDataVector or DataVector, respectively).
const default_aes_scales = {
        :continuous => {:x     => Scale.x_continuous,
                        :x_min => Scale.x_continuous,
                        :x_max => Scale.x_continuous,
                        :y     => Scale.y_continuous,
                        :y_min => Scale.y_continuous,
                        :y_max => Scale.y_continuous,
                        :color => Scale.color_gradient,
                        :label => Scale.label},
        :discrete   => {:x     => Scale.x_discrete,
                        :x_min => Scale.x_discrete,
                        :x_max => Scale.x_discrete,
                        :y     => Scale.y_discrete,
                        :y_min => Scale.y_discrete,
                        :y_max => Scale.y_discrete,
                        :color => Scale.color_hue,
                        :label => Scale.label}}

# Determine whether the input is discrete or continuous.
classify_data{N}(data::AbstractArray{Float64, N}) = :continuous
classify_data{N}(data::AbstractArray{Float32, N}) = :continuous
classify_data{N}(data::DataArray{Float64, N}) = :continuous
classify_data{N}(data::DataArray{Float32, N}) = :continuous
classify_data(data::DataArray) = :discrete
classify_data(data::PooledDataArray) = :discrete

# Very long unfactorized integer data should be treated as continuous
function classify_data{T <: Integer}(data::Union(AbstractArray{T}, DataArray{T}))
    length(Set{T}(data...)) <= 20 ? :discrete : :continuous
end

end # module Gadfly


text:
# ---
# title: 701. Insert into a Binary Search Tree
# id: problem701
# author: Tian Jun
# date: 2020-10-31
# difficulty: Medium
# categories: Tree
# link: <https://leetcode.com/problems/insert-into-a-binary-search-tree/description/>
# hidden: true
# ---
#
# You are given the `root` node of a binary search tree (BST) and a `value` to
# insert into the tree. Return _the root node of the BST after the insertion_.
# It is **guaranteed** that the new value does not exist in the original BST.
#
# **Notice**  that there may exist multiple valid ways for the insertion, as
# long as the tree remains a BST after insertion. You can return **any of
# them**.
#
#
#
# **Example 1:**
#
# ![](https://assets.leetcode.com/uploads/2020/10/05/insertbst.jpg)
#
#
#
#     Input: root = [4,2,7,1,3], val = 5
#     Output: [4,2,7,1,3,5]
#     Explanation: Another accepted tree is:
#     ![](https://assets.leetcode.com/uploads/2020/10/05/bst.jpg)
#
#
# **Example 2:**
#
#
#
#     Input: root = [40,20,60,10,30,50,70], val = 25
#     Output: [40,20,60,10,30,50,70,null,null,25]
#
#
# **Example 3:**
#
#
#
#     Input: root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
#     Output: [4,2,7,1,3,5]
#
#
#
#
# **Constraints:**
#
#   * The number of nodes in the tree will be in the range `[0, 104]`.
#   * `-108 <= Node.val <= 108`
#   * All the values `Node.val` are **unique**.
#   * `-108 <= val <= 108`
#   * It's **guaranteed** that `val` does not exist in the original BST.
#
#
## @lc code=start
using LeetCode

## add your code here:
## @lc code=end


text:
module AbstractFeedbackNets

using ..Splitters
using ..Mergers

export AbstractFeedbackNet, splitnames, namesvalid

"""
    AbstractFeedbackNet

Abstract base type for networks that include handling for feedback.

# Interface

Any subtype should support iteration (over its layers) in order for the generic
method of this type to work.
"""
abstract type AbstractFeedbackNet end

"""
    splitnames(net::AbstractFeedbackNet)

Return the names of all `Splitter`s in `net`.
"""
function splitnames(net::AbstractFeedbackNet)
    names = Vector{String}()
    for layer in net
        if layer isa Splitter
            push!(names, splitname(layer))
        end
    end
    return names
end # function splitnames

"""
    namesvalid(net::AbstractFeedbackNet)

Check if the input names of all `Mergers` in `net` have a corresponding `Splitter`
and that no two `Splitter`s have the same name.
"""
function namesvalid(net::AbstractFeedbackNet)
    splitters = splitnames(net)
    # check that splitter names are unique
    uniqueness = (length(unique(splitters)) == length(splitters))
    # check that merger names have corresponding splitter name
    mergers = Vector{String}()
    for layer in net
        if layer isa Merger
            push!(mergers, inputname(layer))
        end
    end
    all(name in splitters for name in mergers) & uniqueness
end # function namesvalid

end # module AbstractFeedbackNets