text:
#==============================================================================#
# Support.jl
#
# This file is generated from:
# https://github.com/aws/aws-sdk-js/blob/master/apis/support-2013-04-15.normal.json
#==============================================================================#

__precompile__()

module Support

using AWSCore

"""
    using AWSSDK.Support.add_attachments_to_set
    add_attachments_to_set([::AWSConfig], arguments::Dict)
    add_attachments_to_set([::AWSConfig]; attachments=, <keyword arguments>)

    using AWSCore.Services.support
    support([::AWSConfig], "AddAttachmentsToSet", arguments::Dict)
    support([::AWSConfig], "AddAttachmentsToSet", attachments=, <keyword arguments>)

# AddAttachmentsToSet Operation

Adds one or more attachments to an attachment set. If an `attachmentSetId` is not specified, a new attachment set is created, and the ID of the set is returned in the response. If an `attachmentSetId` is specified, the attachments are added to the specified set, if it exists.

An attachment set is a temporary container for attachments that are to be added to a case or case communication. The set is available for one hour after it is created; the `expiryTime` returned in the response indicates when the set expires. The maximum number of attachments in a set is 3, and the maximum size of any attachment in the set is 5 MB.

# Arguments

## `attachmentSetId = ::String`
The ID of the attachment set. If an `attachmentSetId` is not specified, a new attachment set is created, and the ID of the set is returned in the response. If an `attachmentSetId` is specified, the attachments are added to the specified set, if it exists.

## `attachments = [[ ... ], ...]` -- *Required*
One or more attachments to add to the set. The limit is 3 attachments per set, and the size limit is 5 MB per attachment.
```
 attachments = [[
        "fileName" =>  ::String,
        "data" =>  blob
    ], ...]
```

# Returns

`AddAttachmentsToSetResponse`

# Exceptions

`InternalServerError`, `AttachmentSetIdNotFound`, `AttachmentSetExpired`, `AttachmentSetSizeLimitExceeded` or `AttachmentLimitExceeded`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/AddAttachmentsToSet)
"""
@inline add_attachments_to_set(aws::AWSConfig=default_aws_config(); args...) = add_attachments_to_set(aws, args)

@inline add_attachments_to_set(aws::AWSConfig, args) = AWSCore.Services.support(aws, "AddAttachmentsToSet", args)

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

"""
    using AWSSDK.Support.add_communication_to_case
    add_communication_to_case([::AWSConfig], arguments::Dict)
    add_communication_to_case([::AWSConfig]; communicationBody=, <keyword arguments>)

    using AWSCore.Services.support
    support([::AWSConfig], "AddCommunicationToCase", arguments::Dict)
    support([::AWSConfig], "AddCommunicationToCase", communicationBody=, <keyword arguments>)

# AddCommunicationToCase Operation

Adds additional customer communication to an AWS Support case. You use the `caseId` value to identify the case to add communication to. You can list a set of email addresses to copy on the communication using the `ccEmailAddresses` value. The `communicationBody` value contains the text of the communication.

The response indicates the success or failure of the request.

This operation implements a subset of the features of the AWS Support Center.

# Arguments

## `caseId = ::String`
The AWS Support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-*12345678910-2013-c4c1d2bf33c5cf47*

## `communicationBody = ::String` -- *Required*
The body of an email communication to add to the support case.

## `ccEmailAddresses = [::String, ...]`
The email addresses in the CC line of an email to be added to the support case.

## `attachmentSetId = ::String`
The ID of a set of one or more attachments for the communication to add to the case. Create the set by calling [AddAttachmentsToSet](@ref)

# Returns

`AddCommunicationToCaseResponse`

# Exceptions

`InternalServerError`, `CaseIdNotFound`, `AttachmentSetIdNotFound` or `AttachmentSetExpired`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/AddCommunicationToCase)
"""
@inline add_communication_to_case(aws::AWSConfig=default_aws_config(); args...) = add_communication_to_case(aws, args)

@inline add_communication_to_case(aws::AWSConfig, args) = AWSCore.Services.support(aws, "AddCommunicationToCase", args)

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

"""
    using AWSSDK.Support.create_case
    create_case([::AWSConfig], arguments::Dict)
    create_case([::AWSConfig]; subject=, communicationBody=, <keyword arguments>)

    using AWSCore.Services.support
    support([::AWSConfig], "CreateCase", arguments::Dict)
    support([::AWSConfig], "CreateCase", subject=, communicationBody=, <keyword arguments>)

# CreateCase Operation

Creates a new case in the AWS Support Center. This operation is modeled on the behavior of the AWS Support Center [Create Case](https://console.aws.amazon.com/support/home#/case/create) page. Its parameters require you to specify the following information:

*   **issueType.** The type of issue for the case. You can specify either "customer-service" or "technical." If you do not indicate a value, the default is "technical."

*   **serviceCode.** The code for an AWS service. You obtain the `serviceCode` by calling [DescribeServices](@ref).

*   **categoryCode.** The category for the service defined for the `serviceCode` value. You also obtain the category code for a service by calling [DescribeServices](@ref). Each AWS service defines its own set of category codes.

*   **severityCode.** A value that indicates the urgency of the case, which in turn determines the response time according to your service level agreement with AWS Support. You obtain the SeverityCode by calling [DescribeSeverityLevels](@ref).

*   **subject.** The **Subject** field on the AWS Support Center [Create Case](https://console.aws.amazon.com/support/home#/case/create) page.

*   **communicationBody.** The **Description** field on the AWS Support Center [Create Case](https://console.aws.amazon.com/support/home#/case/create) page.

*   **attachmentSetId.** The ID of a set of attachments that has been created by using [AddAttachmentsToSet](@ref).

*   **language.** The human language in which AWS Support handles the case. English and Japanese are currently supported.

*   **ccEmailAddresses.** The AWS Support Center **CC** field on the [Create Case](https://console.aws.amazon.com/support/home#/case/create) page. You can list email addresses to be copied on any correspondence about the case. The account that opens the case is already identified by passing the AWS Credentials in the HTTP POST method or in a method or function call from one of the programming languages supported by an [AWS SDK](http://aws.amazon.com/tools/).

**Note**
> To add additional communication or attachments to an existing case, use [AddCommunicationToCase](@ref).

A successful [CreateCase](@ref) request returns an AWS Support case number. Case numbers are used by the [DescribeCases](@ref) operation to retrieve existing AWS Support cases.

# Arguments

## `subject = ::String` -- *Required*
The title of the AWS Support case.

## `serviceCode = ::String`
The code for the AWS service returned by the call to [DescribeServices](@ref).

## `severityCode = ::String`
The code for the severity level returned by the call to [DescribeSeverityLevels](@ref).

**Note**
> The availability of severity levels depends on each customer's support subscription. In other words, your subscription may not necessarily require the urgent level of response time.

## `categoryCode = ::String`
The category of problem for the AWS Support case.

## `communicationBody = ::String` -- *Required*
The communication body text when you create an AWS Support case by calling [CreateCase](@ref).

## `ccEmailAddresses = [::String, ...]`
A list of email addresses that AWS Support copies on case correspondence.

## `language = ::String`
The ISO 639-1 code for the language in which AWS provides support. AWS Support currently supports English ("en") and Japanese ("ja"). Language parameters must be passed explicitly for operations that take them.

## `issueType = ::String`
The type of issue for the case. You can specify either "customer-service" or "technical." If you do not indicate a value, the default is "technical."

## `attachmentSetId = ::String`
The ID of a set of one or more attachments for the case. Create the set by using [AddAttachmentsToSet](@ref).

# Returns

`CreateCaseResponse`

# Exceptions

`InternalServerError`, `CaseCreationLimitExceeded`, `AttachmentSetIdNotFound` or `AttachmentSetExpired`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/CreateCase)
"""
@inline create_case(aws::AWSConfig=default_aws_config(); args...) = create_case(aws, args)

@inline create_case(aws::AWSConfig, args) = AWSCore.Services.support(aws, "CreateCase", args)

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

"""
    using AWSSDK.Support.describe_attachment
    describe_attachment([::AWSConfig], arguments::Dict)
    describe_attachment([::AWSConfig]; attachmentId=)

    using AWSCore.Services.support
    support([::AWSConfig], "DescribeAttachment", arguments::Dict)
    support([::AWSConfig], "DescribeAttachment", attachmentId=)

# DescribeAttachment Operation

Returns the attachment that has the specified ID. Attachment IDs are generated by the case management system when you add an attachment to a case or case communication. Attachment IDs are returned in the [AttachmentDetails](@ref) objects that are returned by the [DescribeCommunications](@ref) operation.

# Arguments

## `attachmentId = ::String` -- *Required*
The ID of the attachment to return. Attachment IDs are returned by the [DescribeCommunications](@ref) operation.

# Returns

`DescribeAttachmentResponse`

# Exceptions

`InternalServerError`, `DescribeAttachmentLimitExceeded` or `AttachmentIdNotFound`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/DescribeAttachment)
"""
@inline describe_attachment(aws::AWSConfig=default_aws_config(); args...) = describe_attachment(aws, args)

@inline describe_attachment(aws::AWSConfig, args) = AWSCore.Services.support(aws, "DescribeAttachment", args)

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

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

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

# DescribeCases Operation

Returns a list of cases that you specify by passing one or more case IDs. In addition, you can filter the cases by date by setting values for the `afterTime` and `beforeTime` request parameters. You can set values for the `includeResolvedCases` and `includeCommunications` request parameters to control how much information is returned.

Case data is available for 12 months after creation. If a case was created more than 12 months ago, a request for data might cause an error.

The response returns the following in JSON format:

*   One or more [CaseDetails](@ref) data types.

*   One or more `nextToken` values, which specify where to paginate the returned records represented by the `CaseDetails` objects.

# Arguments

## `caseIdList = [::String, ...]`
A list of ID numbers of the support cases you want returned. The maximum number of cases is 100.

## `displayId = ::String`
The ID displayed for a case in the AWS Support Center user interface.

## `afterTime = ::String`
The start date for a filtered date search on support case communications. Case communications are available for 12 months after creation.

## `beforeTime = ::String`
The end date for a filtered date search on support case communications. Case communications are available for 12 months after creation.

## `includeResolvedCases = ::Bool`
Specifies whether resolved support cases should be included in the [DescribeCases](@ref) results. The default is *false*.

## `nextToken = ::String`
A resumption point for pagination.

## `maxResults = ::Int`
The maximum number of results to return before paginating.

## `language = ::String`
The ISO 639-1 code for the language in which AWS provides support. AWS Support currently supports English ("en") and Japanese ("ja"). Language parameters must be passed explicitly for operations that take them.

## `includeCommunications = ::Bool`
Specifies whether communications should be included in the [DescribeCases](@ref) results. The default is *true*.

# Returns

`DescribeCasesResponse`

# Exceptions

`InternalServerError` or `CaseIdNotFound`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/DescribeCases)
"""
@inline describe_cases(aws::AWSConfig=default_aws_config(); args...) = describe_cases(aws, args)

@inline describe_cases(aws::AWSConfig, args) = AWSCore.Services.support(aws, "DescribeCases", args)

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

"""
    using AWSSDK.Support.describe_communications
    describe_communications([::AWSConfig], arguments::Dict)
    describe_communications([::AWSConfig]; caseId=, <keyword arguments>)

    using AWSCore.Services.support
    support([::AWSConfig], "DescribeCommunications", arguments::Dict)
    support([::AWSConfig], "DescribeCommunications", caseId=, <keyword arguments>)

# DescribeCommunications Operation

Returns communications (and attachments) for one or more support cases. You can use the `afterTime` and `beforeTime` parameters to filter by date. You can use the `caseId` parameter to restrict the results to a particular case.

Case data is available for 12 months after creation. If a case was created more than 12 months ago, a request for data might cause an error.

You can use the `maxResults` and `nextToken` parameters to control the pagination of the result set. Set `maxResults` to the number of cases you want displayed on each page, and use `nextToken` to specify the resumption of pagination.

# Arguments

## `caseId = ::String` -- *Required*
The AWS Support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-*12345678910-2013-c4c1d2bf33c5cf47*

## `beforeTime = ::String`
The end date for a filtered date search on support case communications. Case communications are available for 12 months after creation.

## `afterTime = ::String`
The start date for a filtered date search on support case communications. Case communications are available for 12 months after creation.

## `nextToken = ::String`
A resumption point for pagination.

## `maxResults = ::Int`
The maximum number of results to return before paginating.

# Returns

`DescribeCommunicationsResponse`

# Exceptions

`InternalServerError` or `CaseIdNotFound`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/DescribeCommunications)
"""
@inline describe_communications(aws::AWSConfig=default_aws_config(); args...) = describe_communications(aws, args)

@inline describe_communications(aws::AWSConfig, args) = AWSCore.Services.support(aws, "DescribeCommunications", args)

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

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

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

# DescribeServices Operation

Returns the current list of AWS services and a list of service categories that applies to each one. You then use service names and categories in your [CreateCase](@ref) requests. Each AWS service has its own set of categories.

The service codes and category codes correspond to the values that are displayed in the **Service** and **Category** drop-down lists on the AWS Support Center [Create Case](https://console.aws.amazon.com/support/home#/case/create) page. The values in those fields, however, do not necessarily match the service codes and categories returned by the `DescribeServices` request. Always use the service codes and categories obtained programmatically. This practice ensures that you always have the most recent set of service and category codes.

# Arguments

## `serviceCodeList = [::String, ...]`
A JSON-formatted list of service codes available for AWS services.

## `language = ::String`
The ISO 639-1 code for the language in which AWS provides support. AWS Support currently supports English ("en") and Japanese ("ja"). Language parameters must be passed explicitly for operations that take them.

# Returns

`DescribeServicesResponse`

# Exceptions

`InternalServerError`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/DescribeServices)
"""
@inline describe_services(aws::AWSConfig=default_aws_config(); args...) = describe_services(aws, args)

@inline describe_services(aws::AWSConfig, args) = AWSCore.Services.support(aws, "DescribeServices", args)

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

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

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

# DescribeSeverityLevels Operation

Returns the list of severity levels that you can assign to an AWS Support case. The severity level for a case is also a field in the [CaseDetails](@ref) data type included in any [CreateCase](@ref) request.

# Arguments

## `language = ::String`
The ISO 639-1 code for the language in which AWS provides support. AWS Support currently supports English ("en") and Japanese ("ja"). Language parameters must be passed explicitly for operations that take them.

# Returns

`DescribeSeverityLevelsResponse`

# Exceptions

`InternalServerError`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/DescribeSeverityLevels)
"""
@inline describe_severity_levels(aws::AWSConfig=default_aws_config(); args...) = describe_severity_levels(aws, args)

@inline describe_severity_levels(aws::AWSConfig, args) = AWSCore.Services.support(aws, "DescribeSeverityLevels", args)

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

"""
    using AWSSDK.Support.describe_trusted_advisor_check_refresh_statuses
    describe_trusted_advisor_check_refresh_statuses([::AWSConfig], arguments::Dict)
    describe_trusted_advisor_check_refresh_statuses([::AWSConfig]; checkIds=)

    using AWSCore.Services.support
    support([::AWSConfig], "DescribeTrustedAdvisorCheckRefreshStatuses", arguments::Dict)
    support([::AWSConfig], "DescribeTrustedAdvisorCheckRefreshStatuses", checkIds=)

# DescribeTrustedAdvisorCheckRefreshStatuses Operation

Returns the refresh status of the Trusted Advisor checks that have the specified check IDs. Check IDs can be obtained by calling [DescribeTrustedAdvisorChecks](@ref).

**Note**
> Some checks are refreshed automatically, and their refresh statuses cannot be retrieved by using this operation. Use of the `DescribeTrustedAdvisorCheckRefreshStatuses` operation for these checks causes an `InvalidParameterValue` error.

# Arguments

## `checkIds = [::String, ...]` -- *Required*
The IDs of the Trusted Advisor checks to get the status of. **Note:** Specifying the check ID of a check that is automatically refreshed causes an `InvalidParameterValue` error.

# Returns

`DescribeTrustedAdvisorCheckRefreshStatusesResponse`

# Exceptions

`InternalServerError`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/DescribeTrustedAdvisorCheckRefreshStatuses)
"""
@inline describe_trusted_advisor_check_refresh_statuses(aws::AWSConfig=default_aws_config(); args...) = describe_trusted_advisor_check_refresh_statuses(aws, args)

@inline describe_trusted_advisor_check_refresh_statuses(aws::AWSConfig, args) = AWSCore.Services.support(aws, "DescribeTrustedAdvisorCheckRefreshStatuses", args)

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

"""
    using AWSSDK.Support.describe_trusted_advisor_check_result
    describe_trusted_advisor_check_result([::AWSConfig], arguments::Dict)
    describe_trusted_advisor_check_result([::AWSConfig]; checkId=, <keyword arguments>)

    using AWSCore.Services.support
    support([::AWSConfig], "DescribeTrustedAdvisorCheckResult", arguments::Dict)
    support([::AWSConfig], "DescribeTrustedAdvisorCheckResult", checkId=, <keyword arguments>)

# DescribeTrustedAdvisorCheckResult Operation

Returns the results of the Trusted Advisor check that has the specified check ID. Check IDs can be obtained by calling [DescribeTrustedAdvisorChecks](@ref).

The response contains a [TrustedAdvisorCheckResult](@ref) object, which contains these three objects:

*   [TrustedAdvisorCategorySpecificSummary](@ref)

*   [TrustedAdvisorResourceDetail](@ref)

*   [TrustedAdvisorResourcesSummary](@ref)

In addition, the response contains these fields:

*   **status.** The alert status of the check: "ok" (green), "warning" (yellow), "error" (red), or "not_available".

*   **timestamp.** The time of the last refresh of the check.

*   **checkId.** The unique identifier for the check.

# Arguments

## `checkId = ::String` -- *Required*
The unique identifier for the Trusted Advisor check.

## `language = ::String`
The ISO 639-1 code for the language in which AWS provides support. AWS Support currently supports English ("en") and Japanese ("ja"). Language parameters must be passed explicitly for operations that take them.

# Returns

`DescribeTrustedAdvisorCheckResultResponse`

# Exceptions

`InternalServerError`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/DescribeTrustedAdvisorCheckResult)
"""
@inline describe_trusted_advisor_check_result(aws::AWSConfig=default_aws_config(); args...) = describe_trusted_advisor_check_result(aws, args)

@inline describe_trusted_advisor_check_result(aws::AWSConfig, args) = AWSCore.Services.support(aws, "DescribeTrustedAdvisorCheckResult", args)

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

"""
    using AWSSDK.Support.describe_trusted_advisor_check_summaries
    describe_trusted_advisor_check_summaries([::AWSConfig], arguments::Dict)
    describe_trusted_advisor_check_summaries([::AWSConfig]; checkIds=)

    using AWSCore.Services.support
    support([::AWSConfig], "DescribeTrustedAdvisorCheckSummaries", arguments::Dict)
    support([::AWSConfig], "DescribeTrustedAdvisorCheckSummaries", checkIds=)

# DescribeTrustedAdvisorCheckSummaries Operation

Returns the summaries of the results of the Trusted Advisor checks that have the specified check IDs. Check IDs can be obtained by calling [DescribeTrustedAdvisorChecks](@ref).

The response contains an array of [TrustedAdvisorCheckSummary](@ref) objects.

# Arguments

## `checkIds = [::String, ...]` -- *Required*
The IDs of the Trusted Advisor checks.

# Returns

`DescribeTrustedAdvisorCheckSummariesResponse`

# Exceptions

`InternalServerError`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/DescribeTrustedAdvisorCheckSummaries)
"""
@inline describe_trusted_advisor_check_summaries(aws::AWSConfig=default_aws_config(); args...) = describe_trusted_advisor_check_summaries(aws, args)

@inline describe_trusted_advisor_check_summaries(aws::AWSConfig, args) = AWSCore.Services.support(aws, "DescribeTrustedAdvisorCheckSummaries", args)

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

"""
    using AWSSDK.Support.describe_trusted_advisor_checks
    describe_trusted_advisor_checks([::AWSConfig], arguments::Dict)
    describe_trusted_advisor_checks([::AWSConfig]; language=)

    using AWSCore.Services.support
    support([::AWSConfig], "DescribeTrustedAdvisorChecks", arguments::Dict)
    support([::AWSConfig], "DescribeTrustedAdvisorChecks", language=)

# DescribeTrustedAdvisorChecks Operation

Returns information about all available Trusted Advisor checks, including name, ID, category, description, and metadata. You must specify a language code; English ("en") and Japanese ("ja") are currently supported. The response contains a [TrustedAdvisorCheckDescription](@ref) for each check.

# Arguments

## `language = ::String` -- *Required*
The ISO 639-1 code for the language in which AWS provides support. AWS Support currently supports English ("en") and Japanese ("ja"). Language parameters must be passed explicitly for operations that take them.

# Returns

`DescribeTrustedAdvisorChecksResponse`

# Exceptions

`InternalServerError`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/DescribeTrustedAdvisorChecks)
"""
@inline describe_trusted_advisor_checks(aws::AWSConfig=default_aws_config(); args...) = describe_trusted_advisor_checks(aws, args)

@inline describe_trusted_advisor_checks(aws::AWSConfig, args) = AWSCore.Services.support(aws, "DescribeTrustedAdvisorChecks", args)

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

"""
    using AWSSDK.Support.refresh_trusted_advisor_check
    refresh_trusted_advisor_check([::AWSConfig], arguments::Dict)
    refresh_trusted_advisor_check([::AWSConfig]; checkId=)

    using AWSCore.Services.support
    support([::AWSConfig], "RefreshTrustedAdvisorCheck", arguments::Dict)
    support([::AWSConfig], "RefreshTrustedAdvisorCheck", checkId=)

# RefreshTrustedAdvisorCheck Operation

Requests a refresh of the Trusted Advisor check that has the specified check ID. Check IDs can be obtained by calling [DescribeTrustedAdvisorChecks](@ref).

**Note**
> Some checks are refreshed automatically, and they cannot be refreshed by using this operation. Use of the `RefreshTrustedAdvisorCheck` operation for these checks causes an `InvalidParameterValue` error.

The response contains a [TrustedAdvisorCheckRefreshStatus](@ref) object, which contains these fields:

*   **status.** The refresh status of the check: "none", "enqueued", "processing", "success", or "abandoned".

*   **millisUntilNextRefreshable.** The amount of time, in milliseconds, until the check is eligible for refresh.

*   **checkId.** The unique identifier for the check.

# Arguments

## `checkId = ::String` -- *Required*
The unique identifier for the Trusted Advisor check to refresh. **Note:** Specifying the check ID of a check that is automatically refreshed causes an `InvalidParameterValue` error.

# Returns

`RefreshTrustedAdvisorCheckResponse`

# Exceptions

`InternalServerError`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/RefreshTrustedAdvisorCheck)
"""
@inline refresh_trusted_advisor_check(aws::AWSConfig=default_aws_config(); args...) = refresh_trusted_advisor_check(aws, args)

@inline refresh_trusted_advisor_check(aws::AWSConfig, args) = AWSCore.Services.support(aws, "RefreshTrustedAdvisorCheck", args)

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

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

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

# ResolveCase Operation

Takes a `caseId` and returns the initial state of the case along with the state of the case after the call to [ResolveCase](@ref) completed.

# Arguments

## `caseId = ::String`
The AWS Support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-*12345678910-2013-c4c1d2bf33c5cf47*

# Returns

`ResolveCaseResponse`

# Exceptions

`InternalServerError` or `CaseIdNotFound`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/support-2013-04-15/ResolveCase)
"""
@inline resolve_case(aws::AWSConfig=default_aws_config(); args...) = resolve_case(aws, args)

@inline resolve_case(aws::AWSConfig, args) = AWSCore.Services.support(aws, "ResolveCase", args)

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

end # module Support

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


text:
using Pkg
Pkg.activate(".")

using BenchmarkTools
using Distributions
using Flux.Optimise:update!
using Revise
using Flux.Optimise
using Random
using Plots
using ControlSystems

using DifferentialEquations

using CUDA

includet("../models/solvers.jl")
includet("../models/REN.jl")
includet("../models/ffREN.jl")
includet("../train.jl")
includet("../utils.jl")
includet("../PDEs.jl")

plotlyjs()

# Observer design experiment - start with linear system
dtype = Float32
device = gpu

nv = 200

n = 51
m = 1
p = 1

# Generate data
f, g = reaction_diffusion_equation()

nPoints = 100000
X = zeros(n, nPoints)
U = zeros(m, nPoints)
for t in 1:nPoints - 1
    X[:, t + 1:t + 1] = f(X[:, t:t], U[:, t:t])

    # Calculate next u
    u_next = U[1,t] .+ 0.05f0 * randn(dtype)
    if u_next > 1
        u_next = 1
    elseif u_next < 0
        u_next = 0
    end
    U[:,t + 1] .= u_next
end
xt = X[:, 1:end - 1] |> device
xn = X[:, 2:end] |> device
y = g(X, U) |> device

input_data = [device(U); y][:, 1:end - 1]  # inputs to observer
batchsize = 200

data = Flux.Data.DataLoader((xn, xt, input_data), batchsize=batchsize, shuffle=true)

# Model parameters
nx = n
nu = size(input_data, 1)

# Create implicit model
model = implicit_ff_cell{dtype}(nu, nx, nv; nl=tanh, ϵ=0.01f0, bx_scale=0.0) |> device

# Saving and loading a model
# bson("./results/observer_design/ff_ren_nx51_nv200_eps0.01.bson", Dict("model" => cpu(model)))
# testdata = BSON.load("./results/observer_design/ff_ren_nx51_nv200_eps0.01.bson")  # to load model

opt = Flux.Optimise.ADAM(1E-3)
tloss, loss_std = train_observer!(model, data, opt; Epochs=1000, solve_tol=1E-5)

# Test resulting model
T = 1000
time = 1:T

u = ones(dtype, m, length(time)) / 2 |> device
x = ones(dtype, n, length(time)) |> device

for t in 1:T - 1
    x[:, t + 1] = f(x[:, t:t], u[t:t])

    # Calculate next u
    u_next = u[t] + 0.05f0 * (randn(dtype))
    if u_next > 1
        u_next = 1
    elseif u_next < 0
        u_next = 0
    end
    u[t + 1] = u_next
end
y = [g(x[:, t:t], u[t]) for t in time] |> device

# Test Observer
batches = 1
observer_inputs = [repeat([ui; yi], outer=(1, batches)) for (ui, yi) in zip(u, y)] |> device

x0 = zeros(nx, batches) |> device
xhat = collect(simulate(testdata["model"], cpu(x0), cpu(observer_inputs)))[1]

p1 = heatmap(x, color=:cividis, aspect_ratio=1);

Xhat = reduce(hcat, xhat)
p2 = heatmap(Xhat[:, 1:batches:end], color=:cividis, aspect_ratio=1);
p3 = heatmap(abs.(x - Xhat[:, 1:batches:end]), color=:cividis, aspect_ratio=1);

p = plot(p1, p2, p3; layout=(3, 1))

plots = []
for k = 1:6:n
    p = plot(x[k,:])
    push!(plots, p)
    for b in 1:batches
        plot!(extract(xhat, k, b))
    end
    plot!()
end
p = plot(plots...; layout=(3, 3), legend=nothing)

# Plot error
Xhat = reduce(hcat, xhat)
err = Xhat - x
error = map(norm, eachslice(err; dims=2))

p = plot(error; yscale=:log10)

ext: jl

max_stars_repo_name: imanchester/REN

max_issues_repo_name: imanchester/REN

max_forks_repo_name: imanchester/REN


text:
function pressureFunc2p5D( cpfile::String, Vinf::Float64, ρinf::Float64,
                           Λ::Float64,  λ::Float64, AR::Float64,
                           ea::Float64, cr::Float64 )

    data = readdlm( cpfile )

    s = data[:,1]
    inds = find( s[1:end-1] - s[2:end] .> 0.5 )
    ind = inds[1]

    xup = data[     1:ind,1 ]
    xlo = data[ ind+1:end,1 ]
    cpup = data[     1:ind, 5 ]
    cplo = data[ ind+1:end, 5 ]

    if xup[1] > xup[2]
        inds2 = find( xup .== minimum(xup) )
        ind2 = inds2[1]
        xlo  = vcat( xup[ind2:-1:2],  xlo )
        cplo = vcat( cpup[ind2:-1:2], cplo )
        deleteat!( xup,  1:(ind2-1) )
        deleteat!( cpup, 1:(ind2-1) )
    end

    xup = vcat( -1e-4, xup )
    xlo = vcat( -1e-4, xlo )

    cpup = vcat( cpup[1], cpup )
    cplo = vcat( cplo[1], cplo )

    spl_up = Dierckx.Spline1D( xup, cpup )
    spl_lo = Dierckx.Spline1D( xlo, cplo )

    pu( p::Matrix{Float64} ) = hcat( 0.5 * ρinf * Vinf^2 *
                                     getCpwing2p5D(p[:,1:2], Λ, λ, AR, ea, cr, spl_up), 0.0*p[:,2], 0.0*p[:,2] )
    pl( p::Matrix{Float64} ) = hcat( 0.5 * ρinf * Vinf^2 *
                                     getCpwing2p5D(p[:,1:2], Λ, λ, AR, ea, cr, spl_lo), 0.0*p[:,2], 0.0*p[:,2] )

    return (pu, pl)

end

function getCpwing2p5D( p2d::Matrix{Float64}, Λ::Float64, λ::Float64, AR::Float64,
                        ea::Float64, cr::Float64, spl::Dierckx.Spline1D )

    b2    = AR * ( cr + λ ) / 4
    ct    = cr * λ
    c     = cr - p2d[:,2] / b2 * (cr - ct)
    xnorm = (p2d[:,1] - p2d[:,2]*tand(Λ) ) ./ c + ea

    # if maximum(xnorm) >= 1.0
    #     println( "max(xnorm) ", maximum(xnorm) )
    #     ii = find( xnorm .== maximum(xnorm) )
    #     println( "x org ", p2d[ii,:])
    # end
    # if minimum(xnorm) <= 0.0
    #     println( "min(xnorm) ", minimum(xnorm) )
    #     ii = find( xnorm .== minimum(xnorm) )
    #     println( "x org ", p2d[ii,:])
    # end
    # assert( maximum(xnorm) >= 1.0 )
    # assert( minimum(xnorm) <= 0.0 )

    cpc = spl( xnorm ) .* c .* cosd(Λ)

    return cpc

end


text:
include("graphs.jl")
include("fintime_solve.jl")
include("inftime_solve.jl")
include("solve.jl")
include("poisson_trunc.jl")


text:
@generated function Mixer(args...)
    if findfirst(x->x<:New,args)==nothing
        return quote
            error("A method error. Please define what to do for Mixer$args")
        end
    else
        return quote
            return invokelatest(Mixer,unbox(args)...)
        end
    end
end

@generated function Braider(args...)
    if findfirst(x->x<:New,args)==nothing
        return quote
            error("A method error. Please define what to do for Braider$args")
        end
    else
        return quote
            return invokelatest(Braider,unbox(args)...)
        end
    end
end

@generated function SystemConfig(args...)
    if findfirst(x->x<:New,args)==nothing
        return quote
            error("A method error. Please define what to do for SystemConfig$args")
        end
    else
        return quote
            return invokelatest(SystemConfig,unbox(args)...)
        end
    end
end

@generated function save(args...)
    if findfirst(x->x<:New,args)==nothing
        return quote
            error("A method error. Please define what to do for save$args")
        end
    else
        return quote
            return invokelatest(save,unbox(args)...)
        end
    end
end


text:
using Chain
using Underscores
using Utils

@enum Seat::Int8 floor=Int('.') empty=Int('L') occupied=Int('#') void=Int('?')

function parse_line(line::String)::Array{Seat}
    @chain line begin
        collect
        map(Seat ∘ Int, _)
    end
end

function embed(m)
    a, b = size(m)
    re = fill(void, (a+2, b+2))
    re[2:end-1, 2:end-1] = m
    re
end

function parse_file(f)
    m = @chain f begin
        eachline
        map(parse_line, _)
        foldl(hcat, _)
        permutedims
    end
    embed(m)
end

function load()
    open(joinpath(@__DIR__, "11_seats.txt"), "r") do f
        parse_file(f)
    end
end

is_occupied(c) = c == occupied

function step(counter, grid, tolerance)
    a, b = axes(grid)
    prev = copy(grid)
    changed = false

    for i in firstindex(a)+1:lastindex(a)-1, j in firstindex(b)+1:lastindex(b)-1
        co = counter(prev, i, j)
        if prev[i, j] == empty && co == 0
            grid[i, j] = occupied
            changed = true
        elseif is_occupied(prev[i, j]) && co >= tolerance
            grid[i, j] = empty
            changed = true
        end
    end

    changed
end

block_count(grid, i, j) = count(is_occupied, grid[i-1:i+1, j-1:j+1]) - Int(is_occupied(grid[i, j]))

function ex(counter, grid, tolerance)
    grid = copy(grid)

    loop = true
    while loop
        loop = step(counter, grid, tolerance)
    end

    count(is_occupied, grid)
end

ex1(grid) = ex(block_count, grid, 4)

function sight_count(grid, i, j)
    count = 0
    for row in -1:1, col in -1:1
        if (row | col) != 0 # Don't count the center.
            rr = i + row
            cc = j + col
            # No need to check indices, because there's definitely a void boundary.
            while grid[rr, cc] == floor
                rr += row
                cc += col
            end
            count += is_occupied(grid[rr, cc]) |> Int
        end
    end
    count
end

ex2(grid) = ex(sight_count, grid, 5)

grid = load()

println("Stable seating occupied: ", ex1(grid))
println("Number of combinations: ", ex2(grid))

using Test

@testset "Adapter Array" begin
    input = """
        L.LL.LL.LL
        LLLLLLL.LL
        L.L.L..L..
        LLLL.LL.LL
        L.LL.LL.LL
        L.LLLLL.LL
        ..L.L.....
        LLLLLLLLLL
        L.LLLLLL.L
        L.LLLLL.LL
        """

    example = parse_file(IOBuffer(input))

    @testset "example 1" begin
        example = copy(example)
        mini = parse_file(IOBuffer("L.\n.L"))
        @test count(is_occupied, mini) == 0
        step(block_count, mini, 4)
        @test count(is_occupied, mini) == 2
        @test mini[2:end-1, 2:end-1] == [occupied floor; floor occupied]
        @test ex1(example) == 37
    end

    @testset "example 2" begin
        see_eight = """
        .......#.
        ...#.....
        .#.......
        .........
        ..#L....#
        ....#....
        .........
        #........
        ...#.....
        """
        see_eight = see_eight |> IOBuffer |> parse_file

        @test see_eight[5+1, 4+1] == empty
        @test sight_count(see_eight, 5+1, 4+1) == 8

        see_one = """
        .............
        .L.L.#.#.#.#.
        .............
        """
        see_one = see_one |> IOBuffer |> parse_file

        @test see_one[2+1, 2+1] == empty
        @test see_one[2+1, 4+1] == empty
        @test sight_count(see_one, 2+1, 2+1) == 0
        @test sight_count(see_one, 2+1, 4+1) == 1

        see_none = """
        .##.##.
        #.#.#.#
        ##...##
        ...L...
        ##...##
        #.#.#.#
        .##.##.
        """
        see_none = see_none |> IOBuffer |> parse_file

        @test see_none[4+1, 4+1] == empty
        @test sight_count(see_none, 4+1, 4+1) == 0

        example = copy(example)
        @test ex2(example) == 26
    end

    @testset "results" begin
        @test ex1(grid) == 2204
        @test ex2(grid) == 1986
    end
end

max_stars_repo_name: CmdQ/AoC


text:
### A Pluto.jl notebook ###
# v0.14.5

using Markdown
using InteractiveUtils

# ╔═╡ 4918dd79-c97b-45af-bd41-19b8936e2086
using Plots, Combinatorics, PlutoTest

# ╔═╡ 8764aae7-27b7-4426-b97e-8b39f3fda965
using LightGraphs, SimpleWeightedGraphs, GraphPlot

# ╔═╡ e48f4d54-a05a-4cda-8726-36a49b5f2585
plotly()

# ╔═╡ 4bacd010-b0e8-11eb-2df6-6ffa252d136a
md"""
# [Day 13: Knights of the Dinner Table](https://adventofcode.com/2015/day/13)

In years past, the holiday feast with your family hasn't gone so well. Not everyone gets along! This year, you resolve, will be different. You're going to find the optimal seating arrangement and avoid all those awkward conversations.

You start by writing up a list of everyone invited and the amount their happiness would increase or decrease if they were to find themselves sitting next to each other person. You have a circular table that will be just big enough to fit everyone comfortably, and so each person will have exactly two neighbors.

For example, suppose you have only four attendees planned, and you calculate their potential happiness as follows:

```
Alice would gain 54 happiness units by sitting next to Bob.
Alice would lose 79 happiness units by sitting next to Carol.
Alice would lose 2 happiness units by sitting next to David.
Bob would gain 83 happiness units by sitting next to Alice.
Bob would lose 7 happiness units by sitting next to Carol.
Bob would lose 63 happiness units by sitting next to David.
Carol would lose 62 happiness units by sitting next to Alice.
Carol would gain 60 happiness units by sitting next to Bob.
Carol would gain 55 happiness units by sitting next to David.
David would gain 46 happiness units by sitting next to Alice.
David would lose 7 happiness units by sitting next to Bob.
David would gain 41 happiness units by sitting next to Carol.

```

Then, if you seat Alice next to David, Alice would lose `2` happiness units (because David talks so much), but David would gain `46` happiness units (because Alice is such a good listener), for a total change of `44`.

If you continue around the table, you could then seat Bob next to Alice (Bob gains `83`, Alice gains `54`). Finally, seat Carol, who sits next to Bob (Carol gains `60`, Bob loses `7`) and David (Carol gains `55`, David gains `41`). The arrangement looks like this:

```
     +41 +46
+55   David    -2
Carol       Alice
+60    Bob    +54
     -7  +83

```

After trying every other seating arrangement in this hypothetical scenario, you find that this one is the most optimal, with a total change in happiness of `330`.

**What is the total change in happiness for the optimal seating arrangement of the actual guest list?**
"""

# ╔═╡ 99e72bde-a1fd-40b7-b404-7888e39507bb
puzzle_input = """
Alice would gain 54 happiness units by sitting next to Bob.
Alice would lose 81 happiness units by sitting next to Carol.
Alice would lose 42 happiness units by sitting next to David.
Alice would gain 89 happiness units by sitting next to Eric.
Alice would lose 89 happiness units by sitting next to Frank.
Alice would gain 97 happiness units by sitting next to George.
Alice would lose 94 happiness units by sitting next to Mallory.
Bob would gain 3 happiness units by sitting next to Alice.
Bob would lose 70 happiness units by sitting next to Carol.
Bob would lose 31 happiness units by sitting next to David.
Bob would gain 72 happiness units by sitting next to Eric.
Bob would lose 25 happiness units by sitting next to Frank.
Bob would lose 95 happiness units by sitting next to George.
Bob would gain 11 happiness units by sitting next to Mallory.
Carol would lose 83 happiness units by sitting next to Alice.
Carol would gain 8 happiness units by sitting next to Bob.
Carol would gain 35 happiness units by sitting next to David.
Carol would gain 10 happiness units by sitting next to Eric.
Carol would gain 61 happiness units by sitting next to Frank.
Carol would gain 10 happiness units by sitting next to George.
Carol would gain 29 happiness units by sitting next to Mallory.
David would gain 67 happiness units by sitting next to Alice.
David would gain 25 happiness units by sitting next to Bob.
David would gain 48 happiness units by sitting next to Carol.
David would lose 65 happiness units by sitting next to Eric.
David would gain 8 happiness units by sitting next to Frank.
David would gain 84 happiness units by sitting next to George.
David would gain 9 happiness units by sitting next to Mallory.
Eric would lose 51 happiness units by sitting next to Alice.
Eric would lose 39 happiness units by sitting next to Bob.
Eric would gain 84 happiness units by sitting next to Carol.
Eric would lose 98 happiness units by sitting next to David.
Eric would lose 20 happiness units by sitting next to Frank.
Eric would lose 6 happiness units by sitting next to George.
Eric would gain 60 happiness units by sitting next to Mallory.
Frank would gain 51 happiness units by sitting next to Alice.
Frank would gain 79 happiness units by sitting next to Bob.
Frank would gain 88 happiness units by sitting next to Carol.
Frank would gain 33 happiness units by sitting next to David.
Frank would gain 43 happiness units by sitting next to Eric.
Frank would gain 77 happiness units by sitting next to George.
Frank would lose 3 happiness units by sitting next to Mallory.
George would lose 14 happiness units by sitting next to Alice.
George would lose 12 happiness units by sitting next to Bob.
George would lose 52 happiness units by sitting next to Carol.
George would gain 14 happiness units by sitting next to David.
George would lose 62 happiness units by sitting next to Eric.
George would lose 18 happiness units by sitting next to Frank.
George would lose 17 happiness units by sitting next to Mallory.
Mallory would lose 36 happiness units by sitting next to Alice.
Mallory would gain 76 happiness units by sitting next to Bob.
Mallory would lose 34 happiness units by sitting next to Carol.
Mallory would gain 37 happiness units by sitting next to David.
Mallory would gain 40 happiness units by sitting next to Eric.
Mallory would gain 18 happiness units by sitting next to Frank.
Mallory would gain 7 happiness units by sitting next to George.""" |> strip

# ╔═╡ b2ea7fa4-3054-4078-a774-ce304bf84fa6
example_input = "
Alice would gain 54 happiness units by sitting next to Bob.
Alice would lose 79 happiness units by sitting next to Carol.
Alice would lose 2 happiness units by sitting next to David.
Bob would gain 83 happiness units by sitting next to Alice.
Bob would lose 7 happiness units by sitting next to Carol.
Bob would lose 63 happiness units by sitting next to David.
Carol would lose 62 happiness units by sitting next to Alice.
Carol would gain 60 happiness units by sitting next to Bob.
Carol would gain 55 happiness units by sitting next to David.
David would gain 46 happiness units by sitting next to Alice.
David would lose 7 happiness units by sitting next to Bob.
David would gain 41 happiness units by sitting next to Carol." |> strip

# ╔═╡ 994bd490-a709-4b8a-ad86-6c1ca350e203
function parseline(line)
	m = match(r"(\w+) would (\w+) (\d+) happiness units by sitting next to (\w+)", line)
	(
		personA=m[1],
		value=m[2] == "gain" ? parse(Int, m[3]) : -parse(Int, m[3]),
		personB=m[4]
	)
end

# ╔═╡ fc48708b-a89f-4998-a7dc-3ac24e8362d1
map(parseline, split(example_input, "\n"))

# ╔═╡ 717f4ea0-b6a7-4049-b4a3-ce79fef4ec32
function calc_happiness(table, rules)
	by_name = Dict(name => 0 for name in table)
	table2 = vcat(table[2:end], table[1])

	for (a,b) in zip(table, table2)
		for change in filter(r -> r.personA == a && r.personB == b, rules)
			by_name[a] += change.value
		end
		for change in filter(r -> r.personA == b && r.personB == a, rules)
			by_name[b] += change.value
		end
	end

	return sum(values(by_name))
end

# ╔═╡ d726299a-786c-472d-ab10-001bd288f5c1
calc_happiness(["Alice", "Bob", "Carol", "David"], map(parseline, split(example_input, "\n")))

# ╔═╡ bbfd2307-62bf-4eb5-8a40-098d5320db0c
function mosthappy1(rules)
	people = collect(Set(map(rule -> rule.personA, rules)))

	maxhappiness = 0
	for perm in permutations(people)
		maxhappiness = max(maxhappiness, calc_happiness(perm, rules))
	end
	maxhappiness
end

# ╔═╡ eb01dad5-997f-4ff1-bb8c-4bd809c613d3
@assert mosthappy1(map(parseline, split(example_input, "\n"))) == 330

# ╔═╡ 39b98fdd-782f-4614-af12-8ba266bee41a
part1 = mosthappy1(map(parseline, split(puzzle_input, "\n")))

# ╔═╡ e8343b85-aa88-4163-bed1-404264ab23af
@test part1 == 709

# ╔═╡ 62ab159c-6bc5-474b-8ae4-86b3a3f8ef12
md"Your puzzle answer was `709`."

# ╔═╡ 5ca3b7cc-5b66-4365-9c2f-7d1034d3c4f2
md"""
# Part Two

In all the commotion, you realize that you forgot to seat yourself. At this point, you're pretty apathetic toward the whole thing, and your happiness wouldn't really go up or down regardless of who you sit next to. You assume everyone else would be just as ambivalent about sitting next to you, too.

So, add yourself to the list, and give all happiness relationships that involve you a score of `0`.

What is the total change in happiness for the optimal seating arrangement that actually includes yourself?

"""

# ╔═╡ 48782852-f830-4772-b514-d95f8b4a5189
function mosthappy2(rules)
	people = collect(Set(map(rule -> rule.personA, rules)))
	me_rules = copy(rules)

	for person in people
		push!(rules, (personA="me", value=0, personB=person))
		push!(rules, (personA=person, value=0, personB="me"))
	end

	push!(people, "me")
	maxhappiness = 0
	for perm in permutations(people)
		maxhappiness = max(maxhappiness, calc_happiness(perm, rules))
	end
	maxhappiness
end

# ╔═╡ 417da2c9-cbe5-4ca9-a46f-18db168dcd88
part2 = mosthappy2(map(parseline, split(puzzle_input, "\n")))

# ╔═╡ db1e2565-3223-423b-a408-4bd2c680dc62
md"Your puzzle answer was `668`."

# ╔═╡ ff4448b7-73a3-4114-8b31-3ed17c02bc30
@test part2 == 668

# ╔═╡ Cell order:
# ╠═4918dd79-c97b-45af-bd41-19b8936e2086
# ╠═8764aae7-27b7-4426-b97e-8b39f3fda965
# ╠═e48f4d54-a05a-4cda-8726-36a49b5f2585
# ╟─4bacd010-b0e8-11eb-2df6-6ffa252d136a
# ╟─99e72bde-a1fd-40b7-b404-7888e39507bb
# ╟─b2ea7fa4-3054-4078-a774-ce304bf84fa6
# ╠═994bd490-a709-4b8a-ad86-6c1ca350e203
# ╠═fc48708b-a89f-4998-a7dc-3ac24e8362d1
# ╠═717f4ea0-b6a7-4049-b4a3-ce79fef4ec32
# ╠═d726299a-786c-472d-ab10-001bd288f5c1
# ╠═bbfd2307-62bf-4eb5-8a40-098d5320db0c
# ╠═eb01dad5-997f-4ff1-bb8c-4bd809c613d3
# ╠═39b98fdd-782f-4614-af12-8ba266bee41a
# ╠═e8343b85-aa88-4163-bed1-404264ab23af
# ╟─62ab159c-6bc5-474b-8ae4-86b3a3f8ef12
# ╟─5ca3b7cc-5b66-4365-9c2f-7d1034d3c4f2
# ╠═48782852-f830-4772-b514-d95f8b4a5189
# ╠═417da2c9-cbe5-4ca9-a46f-18db168dcd88
# ╟─db1e2565-3223-423b-a408-4bd2c680dc62
# ╠═ff4448b7-73a3-4114-8b31-3ed17c02bc30


text:
# Query incidence matrix in a database table using an iterator. This example queries all the elements of a set of starting vertices, calculates their degrees, and finds the maximum degree.

# Max elements in iterator.
MaxElem = 500

# Create array of starting vertices
Nv0 = 100
v0 = "Out|" .* string.(ceil.(Int,10000*rand(Nv0,1)))

# Set up query iterator
TedgeIt = getiterator(Tedge,MaxElem)

# Start query iterator
E = logical(TedgeIt[:,v0str])

# Initialize AinDeg to accumulate output
EinDeg = Assoc("","","")

# While there are still elements in E
while nnz(E) > 0

    global E, EinDeg

    # Compute in degree
    Etmp = logical(Tedge[getrow(E),:])
    EinDeg = EinDeg + sum(Etmp[:,StartsWith("In|")],1)

    # Get next query
    E = logical(TedgeIt[])
end

# Get vertex with the maximum degree
EmaxInDeg = (EinDeg == maximum(getadj(EinDeg)))


text:
#!/usr/bin/env julia

# Copyright 2018 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import SemanticFlowGraphs: CLI

function expand_paths(path::String)::Vector{String}
  if isfile(path); [ path ]
  elseif isdir(path); readdir(path)
  else String[] end
end

cmds, cmd_args = CLI.parse(ARGS)

# XXX: Reduce load time by only importing extra packages as needed.
# Julia really needs a better solution to this problem...
if first(cmds) == "record"
  paths = expand_paths(cmd_args["path"])
  if any(endswith(path, ".py") for path in paths)
    import PyCall
  end
  if any(endswith(path, ".R") for path in paths)
    import RCall
  end
end

CLI.invoke(cmds, cmd_args)

max_stars_repo_name: cclauss/semanticflowgraph

max_issues_repo_name: cclauss/semanticflowgraph

max_forks_repo_name: cclauss/semanticflowgraph


text:
using CollegeStratBase, CollegeStratWorker
using Random, Test
using ModelParams, UtilityFunctionsLH

const TimeInt = UInt8

csw = CollegeStratWorker;

# function experTest()
# 	@testset "Experience" begin
# 		xp = ExperProductivity(HSG);
# 		xV = collect(1:5);
# 		logProdV = log_exper_prod(xp, xV);
# 		@test length(logProdV) == length(xV)
# 		@test isa(logProdV, Vector{Double})
# 	end
# end

# Where to put this? +++++
# Base.@kwdef struct UtilAll{F1 <: AbstractFloat}
#     discFactor :: F1 = F1(0.9)
#     cCurvature :: F1 = F1(2.5)
#     lCurvature :: F1 = F1(1.5)
#     wtLeisure :: F1 = F1(0.6)
#     leisure_sV :: Vector{F1} = F1.([0.5, 0.1, 0.7, 1.2])
#     hasWorkLeisure :: Bool = true
# end

# function make_test_util_all()
#     return UtilAll{Float64}(discFactor = 0.9)
# end

function access_test()
	@testset "Access routines" begin
		wk = csw.make_test_worker(2);
		@test csw.max_life_span(wk) == csw.life_span(wk, 1)

		workStartAge = 3;
		nc = csw.cons_periods(wk, workStartAge);
		nWork = csw.work_periods(wk, workStartAge);
		nRetire = csw.retire_periods(wk, workStartAge);
		@test nc == (nWork + nRetire)

		workAgeV = csw.work_ages(wk, workStartAge);
		retireAgeV = csw.retire_ages(wk, workStartAge);
		@test length(workAgeV) == nWork;
		@test length(retireAgeV) == nRetire;
		@test workAgeV[nWork] + 1 == retireAgeV[1];
		@test csw.last_work_age(wk, workStartAge) == workAgeV[nWork];
	end
end

function earnings_test()
	@testset "Lifetime earnings" begin
		wk = CollegeStratWorker.make_test_worker(2);
        @test validate_worker(wk);
        println("\n-------------")
		println(wk);

		xV = log_exper_profile(wk, 1; experV = 1 : 10);
		@test xV[1] ≈ 0.0
		@test all(diff(xV) .> 0.0)
		# Giving work start age
		x2V = log_exper_profile(wk, 5);

		workStartAge = 3;
		h0 = 1.5;
		earn10 = earn_profile(wk, workStartAge, h0, experV = 10);
		@test earn10 > 0.0
		@test isa(earn10, AbstractFloat)

		xpV = 7 : 15;
		earnV = earn_profile(wk, workStartAge, h0, experV = xpV);
		@test all(earnV .> 0.0)
		@test size(earnV) == size(xpV)

		hM = [2.0 3.0 4.0; 0.6 0.7 0.8];
		workStartAge = 2;
		ltyV = lifetime_earnings(wk, workStartAge, hM);
		@test all(ltyV .> 0) && (size(ltyV) == size(hM))

		for (j, h) in enumerate(hM)
			lty2 = present_value(earn_profile(wk, workStartAge, h), wk.R);
			@test isapprox(lty2, ltyV[j])
		end

		lty2V = lifetime_earnings(wk, workStartAge + 1, hM);
		@test all(lty2V .< ltyV)

		# Retirement income
		T = csw.life_span(wk, workStartAge);
		incomeV = zeros(T);
		incomeV[csw.retire_ages(wk, workStartAge)] .= csw.retire_income(wk);
		pv = present_value(incomeV, wk.R);
		@test isapprox(pv, csw.pv_retire_income(wk, workStartAge));
	end
end

function consumption_test()
	@testset "Consumption" begin
		w = csw.make_test_worker(3);
		workStartAge = 2;
		ltIncome = [3.4 2.1; 9.2 4.7];
		# Consumption at age 1
		c1 = csw.cons_age1(w, workStartAge, ltIncome);
		@test size(c1) == size(ltIncome)
		@test all(c1 .> 0.0)

		lty = 3.9;
		ltyTotal = lty + csw.pv_retire_income(w, workStartAge);
		c1 = csw.cons_age1(w, workStartAge, lty);
		cV = csw.cons_path(w, workStartAge, lty);
		@test length(cV) == csw.cons_periods(w, workStartAge);
		@test isapprox(cV[1], c1)
		@test isapprox(present_value(cV, w.R), ltyTotal)
    end
end

# function worker_set_test()
#     @testset "WorkerSet" begin
#         nSchool = 4;
# 		wss = WorkerSetSwitches(nSchool = nSchool);
# 		ws = CollegeStratWorker.make_test_worker_set(wss);
# 		utilS = make_test_util_all();
# 		R = 1.04;
#         iSchool = 2;

# 		# Fixed utilities
# 		uFixed = u_fixed(ws, utilS, iSchool);
# 		@test isa(uFixed, Float64)

# 		# Wages
# 		wage_sV = wage_by_school(ws);
# 		# @test length(wage_sV) == nSchool
# 		@test wage(ws, iSchool) ≈ wage_sV[iSchool]

# 		# Make worker
# 		wk = make_worker(ws, utilS, R, iSchool);
# 		print(wk)
# 		@test validate_worker(wk)
# 	end
# end

function simulate_test()
    @testset "Simulation" begin
        rng = MersenneTwister(43);
        nSchool = 4;
        nSim = 11;
        iSchoolV = rand(rng, UInt8.(1 : nSchool), nSim);
        workStartAgeV = rand(rng, TimeInt.(1:5), nSim);
        hWorkStartV = 1.0 .+ 2.0 .* rand(rng, nSim);
        kWorkStartV = rand(rng, nSim) .- 0.1;

        wh = WorkHistories(iSchoolV, workStartAgeV, hWorkStartV, kWorkStartV);
        println("\n--------------")
        println(wh);

        @test length(wh) == nSim
        @test isequal(school_index(wh), iSchoolV)
        @test isequal(work_start_ages(wh), workStartAgeV)
        @test isequal(h_work_start(wh), hWorkStartV)
        @test isequal(k_work_start(wh), kWorkStartV)

		# wss = WorkerSetSwitches(nSchool = nSchool);
		# ws = CollegeStratWorker.make_test_worker_set(wss);
		# utilS = make_test_util_all();
		R = 1.04;
		workerV = [CollegeStratWorker.make_test_worker(iSchool)  for iSchool = 1 : nSchool];

        simulate_workers!(wh, workerV);
        @test validate_wh(wh)

		wh2 = csw.make_test_work_histories(nSchool, nSim);
		@test validate_wh(wh2);
    end
end

@testset "Worker" begin
	access_test();
	earnings_test();
	consumption_test();
	include("lifetime_utility_test.jl");
	include("compensating_var_test.jl");
    # worker_set_test();
    simulate_test();
end

# --------------


text:
function characterize_S3(	particle_type::String,
							R::Array{Float64, 2},
							Lx::Float64,
							Ly::Float64,
							Lz::Float64,
							X::Array{Float64, 1},
							Y::Array{Float64, 1},
							Z::Array{Float64, 1},
							Q0::Array{Float64, 1},
							Q1::Array{Float64, 1},
							Q2::Array{Float64, 1},
							Q3::Array{Float64, 1},
							A11::Array{Float64, 1},
							A12::Array{Float64, 1},
							A13::Array{Float64, 1},
							A21::Array{Float64, 1},
							A22::Array{Float64, 1},
							A23::Array{Float64, 1},
							A31::Array{Float64, 1},
							A32::Array{Float64, 1},
							A33::Array{Float64, 1},
							number_of_samples::Int64,
							d3::Array{Float64, 1},
							theta3::Array{Float64, 1},
							cell_lists::Array{Array{Int64, 1}, 3})

	# Number of cells.
	(number_of_cells_x::Int64, number_of_cells_y::Int64, number_of_cells_z::Int64) = size(cell_lists)

	current_particle_in_cell::Int64 = 0
	is_void::Bool = true

	number_of_distances::Int64 = length(d3)
	number_of_angles::Int64 = length(theta3)

	x0::Float64 = 0.0
	y0::Float64 = 0.0
	z0::Float64 = 0.0

	x_rel::Array{Float64, 2} = zeros(number_of_distances, number_of_angles)
	y_rel::Array{Float64, 2} = zeros(number_of_distances, number_of_angles)
	z_rel::Array{Float64, 2} = zeros(number_of_distances, number_of_angles)
	for current_distance = 1:number_of_distances
		for current_angle = 1:number_of_angles
			x_rel[current_distance, current_angle] = d3[current_distance] * cos(theta3[current_angle])
			y_rel[current_distance, current_angle] = d3[current_distance] * sin(theta3[current_angle])
		end
	end
	x::Array{Float64, 2} = zeros(number_of_distances, number_of_angles)
	y::Array{Float64, 2} = zeros(number_of_distances, number_of_angles)
	z::Array{Float64, 2} = zeros(number_of_distances, number_of_angles)

	indicator_original::BitArray{2} = falses(number_of_distances, number_of_angles)
	indicator::BitArray{2} = falses(number_of_distances, number_of_angles)
	S3::Array{Float64, 3} = zeros(number_of_distances, number_of_distances, convert(Int64, number_of_angles/2 + 1))

	vx::Float64 = 0.0
	vy::Float64 = 0.0
	vz::Float64 = 0.0

	current_cell_x::Int64 = 0
	current_cell_y::Int64 = 0
	current_cell_z::Int64 = 0
	number_of_particles_current_cell::Int64 = 0

	q0::Float64 = 0.0
	q1::Float64 = 0.0
	q2::Float64 = 0.0
	q3::Float64 = 0.0
	a11::Float64 = 0.0
	a12::Float64 = 0.0
	a13::Float64 = 0.0
	a21::Float64 = 0.0
	a22::Float64 = 0.0
	a23::Float64 = 0.0
	a31::Float64 = 0.0
	a32::Float64 = 0.0
	a33::Float64 = 0.0

	for current_sample = 1:number_of_samples
		#if mod(current_sample, 1000) == 0
		#	println(current_sample)
		#end

		# Pick random intial sample position.
		x0 = Lx * rand()
		y0 = Ly * rand()
		z0 = Lz * rand()

		# Check whether void or solid.
		current_cell_x = convert(Int64, ceil(x0 / Lx * convert(Float64, number_of_cells_x)))
		current_cell_y = convert(Int64, ceil(y0 / Ly * convert(Float64, number_of_cells_y)))
		current_cell_z = convert(Int64, ceil(z0 / Lz * convert(Float64, number_of_cells_z)))
		number_of_particles_current_cell = length(cell_lists[current_cell_x, current_cell_y, current_cell_z])
		current_cell_list = cell_lists[current_cell_x, current_cell_y, current_cell_z]

		is_void = true
		current_particle_in_cell = 0
		while current_particle_in_cell < number_of_particles_current_cell && is_void
			current_particle_in_cell += 1

			vx = signed_distance_mod(x0, X[current_cell_list[current_particle_in_cell]], Lx)
			vy = signed_distance_mod(y0, Y[current_cell_list[current_particle_in_cell]], Ly)
			vz = signed_distance_mod(z0, Z[current_cell_list[current_particle_in_cell]], Lz)

			if particle_type == "sphere"
				if vx^2 + vy^2 + vz^2 <= R[current_cell_list[current_particle_in_cell], 1]^2
					is_void = false
				end
			else
				(vx, vy, vz) = (A11[current_cell_list[current_particle_in_cell]] * vx + A12[current_cell_list[current_particle_in_cell]] * vy + A13[current_cell_list[current_particle_in_cell]] * vz,
								A21[current_cell_list[current_particle_in_cell]] * vx + A22[current_cell_list[current_particle_in_cell]] * vy + A23[current_cell_list[current_particle_in_cell]] * vz,
								A31[current_cell_list[current_particle_in_cell]] * vx + A32[current_cell_list[current_particle_in_cell]] * vy + A33[current_cell_list[current_particle_in_cell]] * vz)
				if particle_type == "ellipsoid"
					if  (vx/R[current_cell_list[current_particle_in_cell], 1])^2 +
						(vy/R[current_cell_list[current_particle_in_cell], 2])^2 +
						(vz/R[current_cell_list[current_particle_in_cell], 3])^2 <= 1.0
						is_void = false
					end
				elseif particle_type == "cuboid"
					if abs(vx) <= R[current_cell_list[current_particle_in_cell], 1] && abs(vy) <= R[current_cell_list[current_particle_in_cell], 2] && abs(vz) <= R[current_cell_list[current_particle_in_cell], 3]
						is_void = false
					end
				elseif particle_type == "superellipsoid"
					if  (abs(vx)/R[current_cell_list[current_particle_in_cell], 1])^R[current_cell_list[current_particle_in_cell], 4] +
						(abs(vy)/R[current_cell_list[current_particle_in_cell], 2])^R[current_cell_list[current_particle_in_cell], 4] +
						(abs(vz)/R[current_cell_list[current_particle_in_cell], 3])^R[current_cell_list[current_particle_in_cell], 4] <= 1.0
						is_void = false
					end
				end
			end
		end

		# If origin position is in void, continue analysis.
		if is_void
			# Pick a random orientation.
			(q0, q1, q2, q3) = generate_random_unit_quaternion()
			(a11, a12, a13, a21, a22, a23, a31, a32, a33) = rotation_matrix(q0, q1, q2, q3)

			# Rotate the relative coordinates of the 'template' (as adapted from Hlushkou, 2015)
			# and add the origin coordinate.
			for current_distance = 1:number_of_distances
				for current_angle = 1:number_of_angles
					x[current_distance, current_angle] = x0 + a11 * x_rel[current_distance, current_angle] + a12 * y_rel[current_distance, current_angle] + a13 * z_rel[current_distance, current_angle]
					y[current_distance, current_angle] = y0 + a21 * x_rel[current_distance, current_angle] + a22 * y_rel[current_distance, current_angle] + a23 * z_rel[current_distance, current_angle]
					z[current_distance, current_angle] = z0 + a31 * x_rel[current_distance, current_angle] + a32 * y_rel[current_distance, current_angle] + a33 * z_rel[current_distance, current_angle]
				end
			end

			# Convert to absolute coordinates (w.r.t. to Lx, Ly, Lz)
			for current_distance = 1:number_of_distances
				for current_angle = 1:number_of_angles
					x[current_distance, current_angle] = position_mod(x[current_distance, current_angle], Lx)
					y[current_distance, current_angle] = position_mod(y[current_distance, current_angle], Ly)
					z[current_distance, current_angle] = position_mod(z[current_distance, current_angle], Lz)
				end
			end

			# Check whether void or solid for each sample point.
			for current_distance = 1:number_of_distances
				for current_angle = 1:number_of_angles
					current_cell_x = convert(Int64, ceil(x[current_distance, current_angle] / Lx * convert(Float64, number_of_cells_x)))
					current_cell_y = convert(Int64, ceil(y[current_distance, current_angle] / Ly * convert(Float64, number_of_cells_y)))
					current_cell_z = convert(Int64, ceil(z[current_distance, current_angle] / Lz * convert(Float64, number_of_cells_z)))
					number_of_particles_current_cell = length(cell_lists[current_cell_x, current_cell_y, current_cell_z])
					current_cell_list = cell_lists[current_cell_x, current_cell_y, current_cell_z]

					is_void = true
					current_particle_in_cell = 0
					while current_particle_in_cell < number_of_particles_current_cell && is_void
						current_particle_in_cell += 1

						vx = signed_distance_mod(x[current_distance, current_angle], X[current_cell_list[current_particle_in_cell]], Lx)
						vy = signed_distance_mod(y[current_distance, current_angle], Y[current_cell_list[current_particle_in_cell]], Ly)
						vz = signed_distance_mod(z[current_distance, current_angle], Z[current_cell_list[current_particle_in_cell]], Lz)

						if particle_type == "sphere"
							if vx^2 + vy^2 + vz^2 <= R[current_cell_list[current_particle_in_cell], 1]^2
								is_void = false
							end
						else
							(vx, vy, vz) = (A11[current_cell_list[current_particle_in_cell]] * vx + A12[current_cell_list[current_particle_in_cell]] * vy + A13[current_cell_list[current_particle_in_cell]] * vz,
											A21[current_cell_list[current_particle_in_cell]] * vx + A22[current_cell_list[current_particle_in_cell]] * vy + A23[current_cell_list[current_particle_in_cell]] * vz,
											A31[current_cell_list[current_particle_in_cell]] * vx + A32[current_cell_list[current_particle_in_cell]] * vy + A33[current_cell_list[current_particle_in_cell]] * vz)
							if particle_type == "ellipsoid"
								if  (vx/R[current_cell_list[current_particle_in_cell], 1])^2 +
									(vy/R[current_cell_list[current_particle_in_cell], 2])^2 +
									(vz/R[current_cell_list[current_particle_in_cell], 3])^2 <= 1.0
									is_void = false
								end
							elseif particle_type == "cuboid"
								if abs(vx) <= R[current_cell_list[current_particle_in_cell], 1] && abs(vy) <= R[current_cell_list[current_particle_in_cell], 2] && abs(vz) <= R[current_cell_list[current_particle_in_cell], 3]
									is_void = false
								end
							elseif particle_type == "superellipsoid"
								if  (abs(vx)/R[current_cell_list[current_particle_in_cell], 1])^R[current_cell_list[current_particle_in_cell], 4] +
									(abs(vy)/R[current_cell_list[current_particle_in_cell], 2])^R[current_cell_list[current_particle_in_cell], 4] +
									(abs(vz)/R[current_cell_list[current_particle_in_cell], 3])^R[current_cell_list[current_particle_in_cell], 4] <= 1.0
									is_void = false
								end
							end
						end
					end

					if is_void
						indicator_original[current_distance, current_angle] = true
					else
						indicator_original[current_distance, current_angle] = false
					end
				end
			end

			for current_shift = 0:number_of_angles-1
                indicator = circshift(indicator_original, (0, current_shift))
                for current_r1 = 1:number_of_distances
                    if indicator[current_r1, 1]
						for current_r2 = 1:number_of_distances
							for current_angle = 1:convert(Int64, number_of_angles / 2 + 1)
								if indicator[current_r2, current_angle]
									S3[current_r1, current_r2, current_angle] += 1.0
								end
							end
						end
                    end
                end
            end
		end
	end

	return S3
end


text:
import Config.@if_debug
import RpcApi
import Config
#
# Checks if we need to update statistics data like amount of organisms,
# IPS, best organism parameters and so on. Updates statistics according
# to STAT_UPDATE_PERIOD config.
#
function _updateStat(stamp::Float64)
  local bestOrgs::Array{RpcApi.SimpleOrganism, 1}
  local org::RpcApi.SimpleOrganism
  local json::ASCIIString
  local code::ASCIIString

  if Config.val(:STAT_UPDATE_PERIOD) > 0 && (time() - stamp) > Config.val(:STAT_UPDATE_PERIOD)
    bestOrgs = Manager.getBest(1)
    if length(bestOrgs) > 0
      org  = bestOrgs[1]
      code = string(org.code)
      json = string(
        "{",
        string("\"Probabilities\"       : ", org.mutationProbabilities, ",\n"),
        string("\"Amount of functions\" : ", length(split(code, "function ")) - 2, ",\n"), # minus main function
        string("\"Functions calls\"     : ", length(split(code, "func_")) - 1, ",\n"),
        string("\"Mutations on clone\"  : ", org.mutationsOnClonePercent, ",\n"),
        string("\"Mutations period\"    : ", org.mutationPeriod, ",\n"),
        string("\"Mutations amount\"    : ", org.mutationPercent, ",\n"),
        string("\"Energy\"              : ", org.energy, ",\n"),
        string("\"for operators\"       : ", length(split(code, "for i::Int8")) - 1, ",\n"),
        string("\"if operators\"        : ", length(split(code, "if var")) - 1, ",\n"),
        string("\"getEnergy\"           : ", length(split(code, "Creature.getEnergy")) - 1, ",\n"),
        string("\"Memory reading\"      : ", length(split(code, "haskey(o.mem")) - 1, ",\n"),
        string("\"Eating\"              : ", length(split(code, "Creature.eat")) - 1, ",\n"),
        string("\"Moving\"              : ", length(split(code, "Creature.step")) - 1, ",\n"),
        string("\"Amount of lines\"     : ", org.codeSize, ",\n"),
        string("\"Amount of organisms\" : ", length(Manager._data.tasks), ",\n"),
        string("\"Evals\"               : ", Config.val(:codeRuns), ",\n"),
        string("\"World energy\"        : ", Manager._getWorldEnergy(), ",\n"),
        string("\"Generation number\"   : ", Manager._data.totalOrganisms, "\n"),
        "},\n"
      )
      _appendToFile(json, "file.json")
      _appendToFile(string("{\"Code\": \"", code, "\",\n\"Generation number\": ", Manager._data.totalOrganisms, "},\n"), "code.json")
    end
    return time()
  end

  stamp
end
#
# Appends native values to the file.
# @param data String data to save
# @param file File name, we want append to
# @return {Bool} saving result
#
function _appendToFile(data::ASCIIString, file::ASCIIString)
  local io  = nothing
  local ret = true

  try
    io = open(file, "a") # "a" - means "file append" mode
    write(io, data)
    close(io)
  catch(e)
    warn("ManagerStat._appendToFile(): $e")
    @if_debug showerror(STDOUT, e, catch_backtrace())
    ret = false
  finally
    if io !== nothing close(io) end
  end

  ret
end

max_stars_repo_name: tmptrash/jevo

max_issues_repo_name: tmptrash/jevo

max_forks_repo_name: tmptrash/jevo


text:
function part1(input)
    map = readlines(input)
    return trees(map, 3, 1)
end

function part2(input)
    map = readlines(input)
    slopes = [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]
    return reduce(*, [trees(map, slope...) for slope in slopes])
end

function trees(map, slope_x, slope_y)
    width = length(map[1])
    x, y = 1, 1
    trees = 0
    while y <= length(map)
        trees += map[y][mod1(x, width)] == '#'
        x += slope_x
        y += slope_y
    end
    return trees
end


text:
@alias CVec = ComponentVector

"""
    idvec(A = 4, B = 2, …)

Build a `ComponentVector` (CVec) with the given group names and as many elements per group
as specified. Each element gets a unique ID within the CVec, which is also its index in the
CVec. I.e. the above call yields `CVec(A = [1,2,3,4], B = [5,6])`. Specify `nothing` as the
group size for a scalar element. Example: `idvec(A=nothing, B=1)` ⇒ `CVec(A=1, B=[2])`
"""
function idvec(; kw...)
    cvec = CVec(; (name => _expand(val) for (name, val) in kw)...)
    cvec .= 1:length(cvec)
    return cvec
end
const temp = zero(Int)  # value does not matter; it gets overwritten by `1:length(cvec)` above.
_expand(val::Nothing) = temp
_expand(val::Integer) = fill(temp, val)
_expand(val::CVec)    = val              # allow nested idvecs


text:
abstract type Logger end

struct DoNothingLogger <: Logger end

function log_step(logger::DoNothingLogger, model, save_genotype_as_file = true) end
function save_log(logger::DoNothingLogger) end
function log_birth(logger::DoNothingLogger, model, child, parent = nothing) end
function log_death(logger::DoNothingLogger, model, organism) end

should_terminate(snapshot) = should_terminate(get_logger(snapshot), snapshot)

max_stars_repo_name: tochsner/ALifeBenchmark

max_issues_repo_name: tochsner/ALifeBenchmark

max_forks_repo_name: tochsner/ALifeBenchmark


text:
module Tokens

using MurmurHash3
#using BitFlags

include("checks.jl")
export checkrange,checkulimit

include("nibble.jl")
export Nibble, nibble

include("abstracttoken.jl")
export AbstractToken, usize, category
export offset, isdirect, subtoken
#export T_END ... category constants are exported in tokenconstants.jl

include("substring.jl")
export substring, sswrite

include("packed31.jl")
export Packed31

include("flytoken.jl")
export FlyToken, DirectFly, BufferFly, HybridFly
export DToken, DIRECT_NOTHING, DIRECT_MISSING

include("tokenconstants.jl")
export CATEGORYNAMES

include("token.jl")
export Token, BToken, HToken, Token

include("search.jl")
export locate

include("ioshared.jl")
export IOShared,modify!,put, compressOnPut
export shrink!, ensure_writeable, ensure_readable
export fillup

#using TreeOnVectors
include("tokenvector.jl")
export TokenVector
include("match.jl")
export initialize!, Matcher, ExactMatcher, AnyByteMatcher, RestrictedRegex
export @rr_str

#include("nibblevector.jl")

include("lexer.jl")
export AbstractLexer, ByteLexer, next, addcategory
#export

include("matchimpl.jl")

end # module


text:
#=
    The File contains the BidimSparsik<Real> - the straightforward
        implementation of a Sparse Matrix
    and related funcs

    Overloaded functions:
        get, zero, length, transpose!, prod, empty!, reduce
=#

#=
    Questions to be asked

        - BidimSparsik contains fields `rows/cols` each of which
            is essentially a combination of nested `Dicts`
          So, if Objects are constructed recursively,
            then creating a BidimSparsik object will cost us an instant
            allocation of 2×(2⁴)² buckets for several discontinuous hashtables
          It seems to be quite a number..

          Gleb: 2 * (2^4)^2 = 2^9 = 512 - I would not worry about this too much, but
          let us keep this in mind. Two things:
          1. I am not sure that you will get this number of buckets because you do not
             create 2 * 2^4 Sparsik's immediately. Am I missing something?
          2. Doing
          @btime a = BidimSparsik(10, 10, Vector{Int}(), Vector{Int}(), Dict{Int, Sparsik}(), Dict{Int, Sparsik}())
          on my laptop gives 240 nanoseconds of execution time. I think we can live with this.

          (2⁴ is a default number of buckets in Dict hashtable)

          Alex: On an instantiation of Dict{Any, Dict} object there is an Array of 16 values
                of type `Dict` to be allocated internally. Since it is filled
                with `undef` values on creation, I guess no recursive Dict creation occurs

=#

# TODO:
#           - rewrite in terms of array-subscription

#------------------------------------------------------------------------------

if !isdefined(Main, :(==))
    import Base: ==, !=, +, -, *, get
end

if !isdefined(Main, :Sparsik)
    include("sparsik.jl")
end

#------------------------------------------------------------------------------

# declared mutable for being able to store T ~ `transposed` info
mutable struct BidimSparsik

    # This implementation has `rows` field to store pairs (row_idx, row)
    # for every row of matrix which contains at least 1 nonzero value
    #
    # Field `cols` stores pairs (col_idx, col) and intrinsically duplicates
    # the `rows`

    # dimensions
    m::Int
    n::Int

    # is_transposed
    T::Bool

    # nonzero rows/columns indices
    # Guaranteed to be sorted
    nnz_rows::Vector{Int}
    nnz_cols::Vector{Int}

    # `Dict` of items: Index{Int} => Row{Sparsik}
    # where Row contains at least 1 nonzero value
    rows::Dict{Int, Sparsik}

    # `Dict` of items: Index{Int} => Column{Sparsik}
    # where Column contains at least 1 nonzero value
    cols::Dict{Int, Sparsik}

    # default ctor
    function BidimSparsik(m, n, nnz_rows, nnz_cols, rows, cols)
        return new(m, n, false, nnz_rows, nnz_cols, rows, cols)
    end

end

#------------------------------------------------------------------------------

# transposes matrix modifying the `A` object itself
function transpose!(A::BidimSparsik)
    A.T = !A.T
    return A
end

# transposes the object representation never touching the `A` object
# O(k) where k = length(A)
# note that it is not an overloaded function
function transposed(A::BidimSparsik)
    return transpose!(deepcopy(A))
end

# checks whether the `A` object is `transposed`
# O(1)
# Gleb: this function looks a bit strange to me as there is no such a matrix
#       property "to be transposed", it is more like a detail of your implementation
function is_transposed(A::BidimSparsik)
    return A.T
end

#------------------------------------------------------------------------------

# returns the tuple of `A` dimensions
# (actually, the product of returned elements equals
#    the dimension of the ambient space of `A`)
# O(1)
# Gleb: why do you return n => m, not, say, a tuple?
# Alex: fixed
function Base.size(A::BidimSparsik)
    if is_transposed(A)
        return (A.n, A.m)
    end
    return (A.m, A.n)
end

# returns the ith dimension of `A`
function Base.size(A::BidimSparsik, i::Int)
    return size(A)[i]
end

# returns number of nonzero entries of `A`
# O(k) where k is the number of nonzeroes in `A`
function Base.length(A::BidimSparsik)
    return sum(map(row -> length(row), values(A.rows)))
end

#------------------------------------------------------------------------------

# returns the ith column of `A` or `zero(Sparsik)` if not present
# O(1) (randomized, amortized)
function get_col(A::BidimSparsik, i::Int)
    if is_transposed(A)
        return get(A.rows, i, zero_sparsik(size(A, 2)))
    end
    return get(A.cols, i, zero_sparsik(size(A, 1)))
end

# returns the ith row of `A` or `zero(Sparsik)` if not present
# O(1) (randomized, amortized)
function get_row(A::BidimSparsik, i::Int)
    if is_transposed(A)
        return get(A.cols, i, zero_sparsik(size(A, 1)))
    end
    return get(A.rows, i, zero_sparsik(size(A, 2)))
end

#------------------------------------------------------------------------------

# returns the list of nonzero columns of `A`
# essentially `get_nnz_cols(A) == sort(keys(A.cols))`
# O(1)
function get_nnz_cols(A::BidimSparsik)
    if is_transposed(A)
        return A.nnz_rows
    end
    return A.nnz_cols
end

# returns the list of nonzero rows of `A`
# essentially `get_nnz_rows(A) == sort(keys(A.rows))`
# O(1)
function get_nnz_rows(A::BidimSparsik)
    if is_transposed(A)
        return A.nnz_cols
    end
    return A.nnz_rows
end

#------------------------------------------------------------------------------

# constructs `BidimSparsik` object from
#   `m`           - number of rows
#   `n`           - number of cols
#   `nnz_rows`    - indices of the future matrix rows every of which contains
#       at least one nonzero value
#       Must be sorted
#   `nnz_cols`    - −//−
#   `nnz_coords`  - `Dict` of items ((i, j) => x) where i and j mark
#       the position of the nonzero element in the matrix and x - its value
#
# let k = length(nnz_coords)
# O(k) (randomized, amortized)
function from_COO(m::Int, n::Int, nnz_rows, nnz_cols, nnz_coords)

    new_rows = Dict(map(i -> i => (Vector() => Dict()), nnz_rows))
    new_cols = Dict(map(i -> i => (Vector() => Dict()), nnz_cols))

    for ((i, j), x) in nnz_coords

        push!(new_rows[i][1], j)
        new_rows[i][2][j] = x

        push!(new_cols[j][1], i)
        new_cols[j][2][i] = x

    end

    return BidimSparsik(
        m, n,
        nnz_rows, nnz_cols,
        Dict(map(i -> i[1] => Sparsik(n, i[2]...), collect(new_rows))),
        Dict(map(i -> i[1] => Sparsik(m, i[2]...), collect(new_cols)))
    )
end

#------------------------------------------------------------------------------

# constructs `BidimSparsik` object from
#   `A`           - a collection-like object of 2 dimensions
#
# let n = length(A)
# O(n) (randomized, amortized)
function from_dense(A)
    nnz_rows, nnz_cols = [], []

    # ok
    nonzero_coords = Dict{Pair{Int, Int}, Any}()

    for idx in findall(!iszero, A)
        nonzero_coords[idx[1] => idx[2]] = A[idx]
    end

    nnz_rows = filter(i -> any(!iszero, map(j -> A[i, j], 1 : size(A, 2))),
                        1 : size(A, 1))
    nnz_cols = filter(i -> any(!iszero, map(j -> A[j, i], 1 : size(A, 1))),
                        1 : size(A, 2))

    return from_COO(
        size(A, 1), size(A, 2),
        nnz_rows, nnz_cols,
        nonzero_coords
    )
end

#------------------------------------------------------------------------------

# returns the trace of `A`
# let n be the first dimension of A
#   and k - the number of nonzeroes in A
# O(min(n, k)) (randomized, amortized)
function trace(A::BidimSparsik)
    ans = 0
    for i in get_nnz_rows(A)
        ans += get(A, i, i)
    end
    return ans
end

#------------------------------------------------------------------------------

# returns A + c * B
# note that `length(A)` and `number of nonzeroes in A` are synonyms
# let k = length(A), r = length(B)
# O(k + r) (randomized, amortized)
#
# Gleb: it looks like you do not use reduce function for Sparsik's here,
#       I suggest to do so, hope this will simplify the code
function Base.reduce(A::BidimSparsik, B::BidimSparsik, c)
    m, n = size(A)
    new_nnz_rows, new_nnz_cols = [], []
    new_rows = Dict{Int, Sparsik}()
    new_cols = Dict{Int, Sparsik}()

    for (new_nnz_indices, new_nnz_data) in [new_nnz_rows => new_rows,
                                            new_nnz_cols => new_cols]
        i, j = 1, 1
        A_nnz_rows, B_nnz_rows = get_nnz_rows(A), get_nnz_rows(B)

        while i <= length(A_nnz_rows) || j <= length(B_nnz_rows)

            if i > length(A_nnz_rows)
                push!(new_nnz_indices, B_nnz_rows[j])
                new_nnz_data[B_nnz_rows[j]] = get_row(B, B_nnz_rows[j])
                j += 1
            elseif j > length(B_nnz_rows)
                push!(new_nnz_indices, A_nnz_rows[i])
                new_nnz_data[A_nnz_rows[i]] = get_row(A, A_nnz_rows[i])
                i += 1
            else

                new_row = reduce(get_row(A, A_nnz_rows[i]), get_row(B, B_nnz_rows[j]), c)
                new_idx = A_nnz_rows[i]
                if A_nnz_rows[i] > B_nnz_rows[j]
                    new_idx = B_nnz_rows[j]
                    new_row = get_row(B, B_nnz_rows[j])
                    j += 1
                elseif A_nnz_rows[i] < B_nnz_rows[j]
                    new_idx = A_nnz_rows[i]
                    new_row = get_row(A, A_nnz_rows[i])
                    i += 1
                else
                    i += 1
                    j += 1
                end
                if (!iszero(new_row))
                    push!(new_nnz_indices, new_idx)
                    new_nnz_data[new_idx] = new_row
                end

            end
        end

        transpose!(A)
        transpose!(B)

    end

    return BidimSparsik(
        m, n,
        new_nnz_rows, new_nnz_cols,
        new_rows, new_cols
    )
end

#------------------------------------------------------------------------------

# returns A × B
# let k = length(A), r = length(B)
# O(kr + klogk + rlogr) (randomized, amortized)
#
# Gleb: two thoughts:
#   - I think you can avoid one of the sortings depending on the order of iteration
#     (first i, then j or vice versa)
#   - Maybe you can construct first "a half" of the product
#     (row or col) and then compute the transpose (should be linear in size)
# Combining them, it may be possible to get rid of the log part
#
function Base.prod(A::BidimSparsik, B::BidimSparsik)
    new_nnz_rows = []
    new_nnz_cols = []
    new_coords = Dict{Pair{Int, Int}, Any}()

    for i in get_nnz_rows(A)
        for j in get_nnz_cols(B)

            product = inner_2(get_row(A, i), get_col(B, j))

            if !iszero(product)

                push!(new_nnz_rows, i)
                push!(new_nnz_cols, j)

                new_coords[i => j] = product

            end
        end
    end

    # seems like `unique!` is linear for sorted collections
    unique!(sort!(new_nnz_rows))
    unique!(sort!(new_nnz_cols))

    return from_COO(
        size(A, 1), size(B, 2),
        new_nnz_rows, new_nnz_cols,
        new_coords
    )
end

#------------------------------------------------------------------------------

# returns A × v
# where v is considered to be a column vector
# let k = length(A), r = length(v)
# O(kr) (randomized, amortized)
# to be covered in tests
function apply_vector(A::BidimSparsik, v::Sparsik)
    new_nonzero = []
    new_data = Dict()

    for i in get_nnz_rows(A)
        product = inner_2(get_row(A, i), v)

        if !iszero(product)
            push!(new_nonzero, i)
            new_data[i] = product
        end

    end

    return Sparsik(size(A, 1), new_nonzero, new_data)
end

#------------------------------------------------------------------------------

# returns A * c modifying the `A` object itself
# let k = length(A)
# O(k) (randomized, amortized)
function scale!(A::BidimSparsik, c)
    if iszero(c)
        return empty!(A)
    end

    for k in 1 : 2
        for i in get_nnz_rows(A)
            scale!(get_row(A, i), c)
        end
        transpose!(A)
    end

    return A
end

# returns A * c, does not modify `A`
# let k = length(A)
# O(k) (randomized, amortized)
function scale(A::BidimSparsik, c)
    return scale!(deepcopy(A::BidimSparsik), c)
end

#------------------------------------------------------------------------------

# returns A[i, j] or zero if not present
# O(1) (randomized, amortized)
function Base.get(A::BidimSparsik, i::Int, j::Int)
    # TODO: rewrite
    return get_row(A, i)[j]
end

#------------------------------------------------------------------------------

# erases all entries of `A`
# let k = length(A)
# O(k)
function Base.empty!(A::BidimSparsik)
    empty!(A.nnz_rows)
    empty!(A.rows)
    empty!(A.nnz_cols)
    empty!(A.cols)
    A.T = false
    return A
end

#------------------------------------------------------------------------------

# returns zero matrix of the dimensions of `A`
Base.zero(A::BidimSparsik) = from_COO(size(A)..., [], [], Dict())

#------------------------------------------------------------------------------

# this should be checked in other way
==(A::BidimSparsik, B::BidimSparsik) = (size(A) == size(B) &&
            A.rows == B.rows;
            A.cols == B.cols;
            A.nnz_cols == B.nnz_cols;
            A.nnz_rows == B.nnz_rows)
!=(A::BidimSparsik, u::BidimSparsik) = !(A == B)

+(A::BidimSparsik, B::BidimSparsik) = reduce(A, B, 1)
-(A::BidimSparsik, B::BidimSparsik) = reduce(A, B, -1)
-(A::BidimSparsik) = scale(A, -1)

*(A::BidimSparsik, c) = scale(A, c)
*(c, A::BidimSparsik) = scale(A, c)
*(A::BidimSparsik, B::BidimSparsik) = prod(A, B)

#------------------------------------------------------------------------------

function print_matrix(A::BidimSparsik)
    println("$(join(map(i -> "|$(join(map(j -> get(A, i, j), 1 : A.n), "\t"))|", 1 : A.m), "\n"))")
end

#------------------------------------------------------------------------------


text:
# ==============================================================================
# International Space Station model
# See https://easychair.org/publications/open/4cGr
# ==============================================================================

using ReachabilityBenchmarks, MAT, Reachability, MathematicalSystems,
      MathematicalPredicates, SparseArrays

# ==============================
# Load model
# ==============================
file = matopen(@relpath "iss.mat")
A = sparse(read(file, "A"))
B = read(file, "B")
C = Matrix(read(file, "C")[3, :]')
n = size(A, 1)
Cvec = C[:]
time_horizon = 20.0
X0 = BallInf(zeros(n), 0.0001)

# ==============================
# Time-varying input
# ==============================
U = Hyperrectangle(low=[0.0, 0.8, 0.9], high=[0.1, 1., 1.])
S = ConstrainedLinearControlContinuousSystem(A, B, nothing, U)
iss_TV = InitialValueProblem(S, X0)

# specifications for time-varying input
ISU01 = is_contained_in(HPolyhedron([HalfSpace(Cvec, 0.0005),
                                   HalfSpace(-Cvec, 0.0005)]))
ISS01 = is_contained_in(HPolyhedron([HalfSpace(Cvec, 0.0007),
                                   HalfSpace(-Cvec, 0.0007)]))

# ==============================
# Constant input
# ==============================
using Reachability:add_dimension
A = sparse(read(file, "A"))
Aext = add_dimension(A, 3)
Aext[1:270, 271:273] = B
S = LinearContinuousSystem(Aext)
X0 = X0 * U
iss_CONST = InitialValueProblem(S, X0)
C = hcat(C, [0.0 0.0 0.0])
Cvec = C[1, :]

# specifications for constant input
ISU02 = is_contained_in(HPolyhedron([HalfSpace(Cvec, 0.00017),
                                   HalfSpace(-Cvec, 0.00017)]))
ISS02 = is_contained_in(HPolyhedron([HalfSpace(Cvec, 0.0005),
                                   HalfSpace(-Cvec, 0.0005)]))

max_stars_repo_name: JuliaReach/ReachabilityBenchmarks

max_issues_repo_name: JuliaReach/ReachabilityBenchmarks

max_forks_repo_name: JuliaReach/ReachabilityBenchmarks


text:
module LogRollerCompose

using LogRoller, LogCompose, Logging
import LogCompose: logcompose, log_min_level

log_assumed_level(logger_config::Dict{String,Any}, default::String="Info") = getproperty(Logging, Symbol(get(logger_config, "assumed_level", default)))

function logcompose(::Type{LogRoller.RollingLogger}, config::Dict{String,Any}, logger_config::Dict{String,Any})
    filename = String(strip(logger_config["filename"]))
    @assert !isempty(filename)

    level = log_min_level(logger_config, "Info")
    sizelimit = get(logger_config, "sizelimit", 10240000)
    nfiles = get(logger_config, "nfiles", 5)
    format = Symbol(get(logger_config, "format", "console"))
    @assert format in (:json, :console)
    entry_size_limit = get(logger_config, "entry_sizelimit", LogRoller.DEFAULT_MAX_LOG_ENTRY_SIZE)
    @assert entry_size_limit > 0
    timestamp_identifier = Symbol(get(logger_config, "timestamp_identifier", "time"))

    LogRoller.RollingLogger(filename, sizelimit, nfiles, level; timestamp_identifier=timestamp_identifier, format=format, entry_size_limit=entry_size_limit)
end

function logcompose(::typeof(LogRoller.RollingFileWriterTee), config::Dict{String,Any}, logger_config::Dict{String,Any})
    filename = String(strip(logger_config["filename"]))
    @assert !isempty(filename)

    level = log_assumed_level(logger_config, "Info")
    sizelimit = get(logger_config, "sizelimit", 10240000)
    nfiles = get(logger_config, "nfiles", 5)
    destination_name = logger_config["destination"]
    destination = LogCompose.logger(config, destination_name)
    LogRoller.RollingFileWriterTee(filename, sizelimit, nfiles, destination, level)
end

function logcompose(::typeof(LogRoller.RollingFileWriter), config::Dict{String,Any}, logger_config::Dict{String,Any})
    filename = String(strip(logger_config["filename"]))
    @assert !isempty(filename)

    level = log_assumed_level(logger_config, "Info")
    sizelimit = get(logger_config, "sizelimit", 10240000)
    nfiles = get(logger_config, "nfiles", 5)
    LogRoller.RollingFileWriter(filename, sizelimit, nfiles)
end

end # module