text:
# Test simple indexing
r = AR(ContinuousRoots(randn(2)))
m = TimeVaryingAR([r,r,r])

@test length(m) == 3*2
@test size(m) == (2,3)
mc = SpectralDistances.change_precision(Float32, m)
@test m ≈ mc
@test eltype(mc.models[1].pc) == Complex{Float32}

@test m[1] == m[1,1]
@test m[2] == m[2,1]
@test m[3] == m[1,2]
@test m[4] == m[2,2]

D = SpectralDistances.distmat_euclidean(m,m,2,2,1)
@test all(iszero, diag(D))
@test D[1,3] == 1
@test D[1,2] != 1
@test D[1,5] == 2^2

D = SpectralDistances.distmat_euclidean(m,m,1,1,1)
@test all(iszero, diag(D))
@test D[1,3] == 1
@test D[1,2] != 1
@test D[1,5] == 2^1

# test fitting
fm = TimeWindow(LS(na=2), 1000, 500)
y = randn(10000)
m = fm(y)
fitmodel(fm, y, showprogress=false)

y2 = randn(10000)
m2 = fm(y2)

@test m[1] == m[1,1]
@test m[2] == m[2,1]
@test m[3] == m[1,2]
@test m[4] == m[2,2]

D = SpectralDistances.distmat_euclidean(m,m,2,2,1)
@test all(iszero, diag(D))

# test that the distance increases as expected with varying frequencies, p=1
dist = TimeDistance(inner=OptimalTransportRootDistance(domain=Continuous(), p=1, weight=simplex_residueweight), tp=1, c=1.0)
dist2 = TimeDistance(inner=KernelWassersteinRootDistance(), tp=2, c=1.0)

@test evaluate(dist, m, m) < 1e-3
@test evaluate(dist, m, m2, iters=10000, tol=1e-3) > 0.1

@test evaluate(dist2, m, m) == 0
@test evaluate(dist2, m, m2) > 0.0001

fm = TimeWindow(LS(na=2), 1000, 500)
y = sin.(0:0.1:100)
m = fm(y)

dist = TimeDistance(inner=OptimalTransportRootDistance(domain=Continuous(), p=1, weight=simplex_residueweight), tp=1, c=1.0)
dists = map([1,2,3,4,5]) do f
    y2 = sin.((0:0.1:100).*f)
    m2 = fm(y2)
    evaluate(dist, m, m2, iters=10000, tol=1e-3)
end

@test all(>(0), diff(dists))
@test dists ≈ 0.1*(0:4) atol=1e-3

# test that the distance increases as expected with varying frequencies, p=2
dist = TimeDistance(inner=OptimalTransportRootDistance(domain=Continuous(), p=2, weight=simplex_residueweight), tp=1, c=1.0)
dists = map([1,2,3,4,5]) do f
    y2 = sin.((0:0.1:100).*f)
    m2 = fm(y2)
    evaluate(dist, m, m2, iters=10000, tol=1e-3)
end

@test all(>(0), diff(dists))
@test dists ≈ (0.1*(0:4)).^2 atol=1e-3

# Construct a signal that changes freq after half
signal(f1,f2) = [sin.((0:0.1:49.9).*f1);sin.((50:0.1:99.9).*f2)]
fm = TimeWindow(LS(na=2), 500, 0)
m = signal(1,2)  |> fm
m2 = signal(2,1) |> fm
# Mess with c such that it becomes cheap to transport in time
dist = TimeDistance(inner=OptimalTransportRootDistance(domain=Continuous(), p=1, weight=simplex_residueweight), tp=1, c=1.0)
d = evaluate(dist, m, m2, iters=10000, tol=1e-3)
@test d ≈ 0.1 rtol=5e-2

dist = TimeDistance(inner=OptimalTransportRootDistance(domain=Continuous(), p=1, weight=simplex_residueweight, β=0.001), tp=1, c=0.01)
d = evaluate(dist, m, m2, iters=10000, tol=1e-5)
@test d ≈ 0.01 rtol=5e-2

## Test distmat

D = distmat(dist, [m, m2])
@test size(D) == (2,2)
@test D[1,1] ≈ dist(m,m)
@test D[1,2] ≈ dist(m,m2)

## Test distmat

D2 = distmat(dist2, [m, m2])
@test size(D2) == (2,2)
@test D2[1,1] ≈ dist2(m,m)
@test D2[1,2] ≈ dist2(m,m2)

## Test resize

D = randn(2,2)
D = resize!(D, 3, 3)
@test size(D) == (3,3)

## Test chirps

fs = 100000
T = 3
t = 0:1/fs:T
N = length(t)
f = range(1000, stop=10_000, length=N)
chirp0 = sin.(f.*t)
function chirp(onset)
    y = 0.1sin.(20_000 .* t)
    inds = max(round(Int,fs*onset), 1):N
    y[inds] .+= chirp0[1:length(inds)]
    y
end
isinteractive() && begin
    @eval using SpectralDistances, DSP, LPVSpectral, ThreadPools
    plot(spectrogram(chirp(0), window=hanning), layout=2)
    plot!(spectrogram(chirp(1), window=hanning), sp=2)
end
fm = TimeWindow(LS(na=4, λ=1e-4), 20000, 0)
m = chirp(1)  |> fm
# @show length(m)

onsets = LinRange(0, 2, 21); 1 ∈ onsets
cv = exp10.(LinRange(-3, -0.5, 6))

@time dists = map(Iterators.product(cv,onsets)) do (c,onset)
    m2 = chirp(onset) |> fm
    dist = TimeDistance(inner=OptimalTransportRootDistance(domain=Continuous(), p=1, weight=simplex_residueweight), tp=1, c=c)
    evaluate(dist, change_precision(Float64, m), change_precision(Float64, m2), iters=10000, tol=1e-2)
end

isinteractive() && plot(onsets, dists', lab=cv', line_z = log10.(cv)', color=:inferno, legend=false, colorbar=true, xlabel="Onset [s]", )


text:
using Lazy

const tracker = Channel{String}(30)
const images = Channel{String}(30)
const path = @> "~/.local/share/koneko/cache/2232374/1" expanduser readdir(join=true, sort=false)

function consumer()
    try
        while true
            img = @> tracker take!
            @> images put!(img)
        end
    catch InvalidStateException
        @> images close
    end
end

function producer(files::Array{String})
    for file in files
        @> tracker put!(file)
    end
    @> tracker close
end

function display()
    left_shifts = [2, 20, 38, 56, 74]
    rowspaces = [0, 9]
    args = "--silent"  # Align doesn't work for some reason
    place = "--place=15x15@"
    try
        while true
            img = @> images take!
            number = @as x img begin
                split(x, "/")[end]
                split(x, "_")[1]
                parse(Int, x)
            end
            x = @> number mod(5)
            y = @> number div(5) mod(2)
            xcoord = left_shifts[x+1]
            ycoord = rowspaces[y+1]

            if number == 10
                @> "\n" repeat(40) println
            elseif number == 20
                @> "\n" repeat(18) println
            end

            @> `kitty +kitten icat $(args) $(place)$(xcoord)x$(ycoord) $img` run

        end
    catch InvalidStateException
        return
    end
end

function main(path)
    @async producer(path)
    @async consumer()
    display()
end

#using InteractiveUtils, Test
#@async producer(path)
#@async consumer()
#@inferred display()
#@code_warntype display()

main(path)

ext: jl


text: println("hello world")

max_issues_repo_name: abhijith-das/Hacktoberfest

max_forks_repo_name: abhijith-das/Hacktoberfest


text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: amplifybackend
using AWS.Compat
using AWS.UUIDs

"""
    clone_backend(app_id, backend_environment_name, target_environment_name)
    clone_backend(app_id, backend_environment_name, target_environment_name, params::Dict{String,<:Any})

This operation clones an existing backend.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `target_environment_name`: The name of the destination backend environment to be created.

"""
function clone_backend(
    appId,
    backendEnvironmentName,
    targetEnvironmentName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/environments/$(backendEnvironmentName)/clone",
        Dict{String,Any}("targetEnvironmentName" => targetEnvironmentName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function clone_backend(
    appId,
    backendEnvironmentName,
    targetEnvironmentName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/environments/$(backendEnvironmentName)/clone",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("targetEnvironmentName" => targetEnvironmentName),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_backend(app_id, app_name, backend_environment_name)
    create_backend(app_id, app_name, backend_environment_name, params::Dict{String,<:Any})

This operation creates a backend for an Amplify app. Backends are automatically created at
the time of app creation.

# Arguments
- `app_id`: The app ID.
- `app_name`: The name of the app.
- `backend_environment_name`: The name of the backend environment.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"resourceConfig"`: The resource configuration for creating backend storage.
- `"resourceName"`: The name of the resource.
"""
function create_backend(
    appId,
    appName,
    backendEnvironmentName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend",
        Dict{String,Any}(
            "appId" => appId,
            "appName" => appName,
            "backendEnvironmentName" => backendEnvironmentName,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_backend(
    appId,
    appName,
    backendEnvironmentName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "appId" => appId,
                    "appName" => appName,
                    "backendEnvironmentName" => backendEnvironmentName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_backend_api(app_id, backend_environment_name, resource_config, resource_name)
    create_backend_api(app_id, backend_environment_name, resource_config, resource_name, params::Dict{String,<:Any})

Creates a new backend API resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_config`: The resource configuration for this request.
- `resource_name`: The name of this resource.

"""
function create_backend_api(
    appId,
    backendEnvironmentName,
    resourceConfig,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api",
        Dict{String,Any}(
            "backendEnvironmentName" => backendEnvironmentName,
            "resourceConfig" => resourceConfig,
            "resourceName" => resourceName,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_backend_api(
    appId,
    backendEnvironmentName,
    resourceConfig,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "backendEnvironmentName" => backendEnvironmentName,
                    "resourceConfig" => resourceConfig,
                    "resourceName" => resourceName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_backend_auth(app_id, backend_environment_name, resource_config, resource_name)
    create_backend_auth(app_id, backend_environment_name, resource_config, resource_name, params::Dict{String,<:Any})

Creates a new backend authentication resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_config`: The resource configuration for this request object.
- `resource_name`: The name of this resource.

"""
function create_backend_auth(
    appId,
    backendEnvironmentName,
    resourceConfig,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/auth",
        Dict{String,Any}(
            "backendEnvironmentName" => backendEnvironmentName,
            "resourceConfig" => resourceConfig,
            "resourceName" => resourceName,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_backend_auth(
    appId,
    backendEnvironmentName,
    resourceConfig,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/auth",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "backendEnvironmentName" => backendEnvironmentName,
                    "resourceConfig" => resourceConfig,
                    "resourceName" => resourceName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_backend_config(app_id)
    create_backend_config(app_id, params::Dict{String,<:Any})

Creates a config object for a backend.

# Arguments
- `app_id`: The app ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"backendManagerAppId"`: The app ID for the backend manager.
"""
function create_backend_config(appId; aws_config::AbstractAWSConfig=global_aws_config())
    return amplifybackend(
        "POST",
        "/backend/$(appId)/config";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_backend_config(
    appId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/config",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_backend_storage(app_id, backend_environment_name, resource_config, resource_name)
    create_backend_storage(app_id, backend_environment_name, resource_config, resource_name, params::Dict{String,<:Any})

Creates a backend storage resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_config`: The resource configuration for creating backend storage.
- `resource_name`: The name of the storage resource.

"""
function create_backend_storage(
    appId,
    backendEnvironmentName,
    resourceConfig,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/storage",
        Dict{String,Any}(
            "backendEnvironmentName" => backendEnvironmentName,
            "resourceConfig" => resourceConfig,
            "resourceName" => resourceName,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_backend_storage(
    appId,
    backendEnvironmentName,
    resourceConfig,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/storage",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "backendEnvironmentName" => backendEnvironmentName,
                    "resourceConfig" => resourceConfig,
                    "resourceName" => resourceName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_token(app_id)
    create_token(app_id, params::Dict{String,<:Any})

Generates a one-time challenge code to authenticate a user into your Amplify Admin UI.

# Arguments
- `app_id`: The app ID.

"""
function create_token(appId; aws_config::AbstractAWSConfig=global_aws_config())
    return amplifybackend(
        "POST",
        "/backend/$(appId)/challenge";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_token(
    appId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/challenge",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_backend(app_id, backend_environment_name)
    delete_backend(app_id, backend_environment_name, params::Dict{String,<:Any})

Removes an existing environment from your Amplify project.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.

"""
function delete_backend(
    appId, backendEnvironmentName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/environments/$(backendEnvironmentName)/remove";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_backend(
    appId,
    backendEnvironmentName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/environments/$(backendEnvironmentName)/remove",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_backend_api(app_id, backend_environment_name, resource_name)
    delete_backend_api(app_id, backend_environment_name, resource_name, params::Dict{String,<:Any})

Deletes an existing backend API resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_name`: The name of this resource.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"resourceConfig"`: Defines the resource configuration for the data model in your Amplify
  project.
"""
function delete_backend_api(
    appId,
    backendEnvironmentName,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api/$(backendEnvironmentName)/remove",
        Dict{String,Any}("resourceName" => resourceName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_backend_api(
    appId,
    backendEnvironmentName,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api/$(backendEnvironmentName)/remove",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("resourceName" => resourceName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_backend_auth(app_id, backend_environment_name, resource_name)
    delete_backend_auth(app_id, backend_environment_name, resource_name, params::Dict{String,<:Any})

Deletes an existing backend authentication resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_name`: The name of this resource.

"""
function delete_backend_auth(
    appId,
    backendEnvironmentName,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/auth/$(backendEnvironmentName)/remove",
        Dict{String,Any}("resourceName" => resourceName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_backend_auth(
    appId,
    backendEnvironmentName,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/auth/$(backendEnvironmentName)/remove",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("resourceName" => resourceName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_backend_storage(app_id, backend_environment_name, resource_name, service_name)
    delete_backend_storage(app_id, backend_environment_name, resource_name, service_name, params::Dict{String,<:Any})

Removes the specified backend storage resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_name`: The name of the storage resource.
- `service_name`: The name of the storage service.

"""
function delete_backend_storage(
    appId,
    backendEnvironmentName,
    resourceName,
    serviceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/storage/$(backendEnvironmentName)/remove",
        Dict{String,Any}("resourceName" => resourceName, "serviceName" => serviceName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_backend_storage(
    appId,
    backendEnvironmentName,
    resourceName,
    serviceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/storage/$(backendEnvironmentName)/remove",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "resourceName" => resourceName, "serviceName" => serviceName
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_token(app_id, session_id)
    delete_token(app_id, session_id, params::Dict{String,<:Any})

Deletes the challenge token based on the given appId and sessionId.

# Arguments
- `app_id`: The app ID.
- `session_id`: The session ID.

"""
function delete_token(appId, sessionId; aws_config::AbstractAWSConfig=global_aws_config())
    return amplifybackend(
        "POST",
        "/backend/$(appId)/challenge/$(sessionId)/remove";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_token(
    appId,
    sessionId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/challenge/$(sessionId)/remove",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    generate_backend_apimodels(app_id, backend_environment_name, resource_name)
    generate_backend_apimodels(app_id, backend_environment_name, resource_name, params::Dict{String,<:Any})

Generates a model schema for an existing backend API resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_name`: The name of this resource.

"""
function generate_backend_apimodels(
    appId,
    backendEnvironmentName,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api/$(backendEnvironmentName)/generateModels",
        Dict{String,Any}("resourceName" => resourceName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function generate_backend_apimodels(
    appId,
    backendEnvironmentName,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api/$(backendEnvironmentName)/generateModels",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("resourceName" => resourceName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_backend(app_id)
    get_backend(app_id, params::Dict{String,<:Any})

Provides project-level details for your Amplify UI project.

# Arguments
- `app_id`: The app ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"backendEnvironmentName"`: The name of the backend environment.
"""
function get_backend(appId; aws_config::AbstractAWSConfig=global_aws_config())
    return amplifybackend(
        "POST",
        "/backend/$(appId)/details";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_backend(
    appId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/details",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_backend_api(app_id, backend_environment_name, resource_name)
    get_backend_api(app_id, backend_environment_name, resource_name, params::Dict{String,<:Any})

Gets the details for a backend API.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_name`: The name of this resource.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"resourceConfig"`: Defines the resource configuration for the data model in your Amplify
  project.
"""
function get_backend_api(
    appId,
    backendEnvironmentName,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api/$(backendEnvironmentName)/details",
        Dict{String,Any}("resourceName" => resourceName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_backend_api(
    appId,
    backendEnvironmentName,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api/$(backendEnvironmentName)/details",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("resourceName" => resourceName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_backend_apimodels(app_id, backend_environment_name, resource_name)
    get_backend_apimodels(app_id, backend_environment_name, resource_name, params::Dict{String,<:Any})

Generates a model schema for existing backend API resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_name`: The name of this resource.

"""
function get_backend_apimodels(
    appId,
    backendEnvironmentName,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api/$(backendEnvironmentName)/getModels",
        Dict{String,Any}("resourceName" => resourceName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_backend_apimodels(
    appId,
    backendEnvironmentName,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api/$(backendEnvironmentName)/getModels",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("resourceName" => resourceName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_backend_auth(app_id, backend_environment_name, resource_name)
    get_backend_auth(app_id, backend_environment_name, resource_name, params::Dict{String,<:Any})

Gets a backend auth details.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_name`: The name of this resource.

"""
function get_backend_auth(
    appId,
    backendEnvironmentName,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/auth/$(backendEnvironmentName)/details",
        Dict{String,Any}("resourceName" => resourceName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_backend_auth(
    appId,
    backendEnvironmentName,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/auth/$(backendEnvironmentName)/details",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("resourceName" => resourceName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_backend_job(app_id, backend_environment_name, job_id)
    get_backend_job(app_id, backend_environment_name, job_id, params::Dict{String,<:Any})

Returns information about a specific job.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `job_id`: The ID for the job.

"""
function get_backend_job(
    appId, backendEnvironmentName, jobId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return amplifybackend(
        "GET",
        "/backend/$(appId)/job/$(backendEnvironmentName)/$(jobId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_backend_job(
    appId,
    backendEnvironmentName,
    jobId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "GET",
        "/backend/$(appId)/job/$(backendEnvironmentName)/$(jobId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_backend_storage(app_id, backend_environment_name, resource_name)
    get_backend_storage(app_id, backend_environment_name, resource_name, params::Dict{String,<:Any})

Gets details for a backend storage resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_name`: The name of the storage resource.

"""
function get_backend_storage(
    appId,
    backendEnvironmentName,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/storage/$(backendEnvironmentName)/details",
        Dict{String,Any}("resourceName" => resourceName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_backend_storage(
    appId,
    backendEnvironmentName,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/storage/$(backendEnvironmentName)/details",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("resourceName" => resourceName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_token(app_id, session_id)
    get_token(app_id, session_id, params::Dict{String,<:Any})

Gets the challenge token based on the given appId and sessionId.

# Arguments
- `app_id`: The app ID.
- `session_id`: The session ID.

"""
function get_token(appId, sessionId; aws_config::AbstractAWSConfig=global_aws_config())
    return amplifybackend(
        "GET",
        "/backend/$(appId)/challenge/$(sessionId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_token(
    appId,
    sessionId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "GET",
        "/backend/$(appId)/challenge/$(sessionId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    import_backend_auth(app_id, backend_environment_name, native_client_id, user_pool_id, web_client_id)
    import_backend_auth(app_id, backend_environment_name, native_client_id, user_pool_id, web_client_id, params::Dict{String,<:Any})

Imports an existing backend authentication resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `native_client_id`: The ID of the Amazon Cognito native client.
- `user_pool_id`: The ID of the Amazon Cognito user pool.
- `web_client_id`: The ID of the Amazon Cognito web client.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"identityPoolId"`: The ID of the Amazon Cognito identity pool.
"""
function import_backend_auth(
    appId,
    backendEnvironmentName,
    nativeClientId,
    userPoolId,
    webClientId;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/auth/$(backendEnvironmentName)/import",
        Dict{String,Any}(
            "nativeClientId" => nativeClientId,
            "userPoolId" => userPoolId,
            "webClientId" => webClientId,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function import_backend_auth(
    appId,
    backendEnvironmentName,
    nativeClientId,
    userPoolId,
    webClientId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/auth/$(backendEnvironmentName)/import",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "nativeClientId" => nativeClientId,
                    "userPoolId" => userPoolId,
                    "webClientId" => webClientId,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    import_backend_storage(app_id, backend_environment_name, service_name)
    import_backend_storage(app_id, backend_environment_name, service_name, params::Dict{String,<:Any})

Imports an existing backend storage resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `service_name`: The name of the storage service.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"bucketName"`: The name of the S3 bucket.
"""
function import_backend_storage(
    appId,
    backendEnvironmentName,
    serviceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/storage/$(backendEnvironmentName)/import",
        Dict{String,Any}("serviceName" => serviceName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function import_backend_storage(
    appId,
    backendEnvironmentName,
    serviceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/storage/$(backendEnvironmentName)/import",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("serviceName" => serviceName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_backend_jobs(app_id, backend_environment_name)
    list_backend_jobs(app_id, backend_environment_name, params::Dict{String,<:Any})

Lists the jobs for the backend of an Amplify app.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"jobId"`: The ID for the job.
- `"maxResults"`: The maximum number of results that you want in the response.
- `"nextToken"`: The token for the next set of results.
- `"operation"`: Filters the list of response objects to include only those with the
  specified operation name.
- `"status"`: Filters the list of response objects to include only those with the specified
  status.
"""
function list_backend_jobs(
    appId, backendEnvironmentName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/job/$(backendEnvironmentName)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_backend_jobs(
    appId,
    backendEnvironmentName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/job/$(backendEnvironmentName)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_s3_buckets()
    list_s3_buckets(params::Dict{String,<:Any})

The list of S3 buckets in your account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"nextToken"`: Reserved for future use.
"""
function list_s3_buckets(; aws_config::AbstractAWSConfig=global_aws_config())
    return amplifybackend(
        "POST", "/s3Buckets"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_s3_buckets(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return amplifybackend(
        "POST", "/s3Buckets", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

"""
    remove_all_backends(app_id)
    remove_all_backends(app_id, params::Dict{String,<:Any})

Removes all backend environments from your Amplify project.

# Arguments
- `app_id`: The app ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"cleanAmplifyApp"`: Cleans up the Amplify Console app if this value is set to true.
"""
function remove_all_backends(appId; aws_config::AbstractAWSConfig=global_aws_config())
    return amplifybackend(
        "POST",
        "/backend/$(appId)/remove";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function remove_all_backends(
    appId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/remove",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    remove_backend_config(app_id)
    remove_backend_config(app_id, params::Dict{String,<:Any})

Removes the AWS resources required to access the Amplify Admin UI.

# Arguments
- `app_id`: The app ID.

"""
function remove_backend_config(appId; aws_config::AbstractAWSConfig=global_aws_config())
    return amplifybackend(
        "POST",
        "/backend/$(appId)/config/remove";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function remove_backend_config(
    appId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/config/remove",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_backend_api(app_id, backend_environment_name, resource_name)
    update_backend_api(app_id, backend_environment_name, resource_name, params::Dict{String,<:Any})

Updates an existing backend API resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_name`: The name of this resource.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"resourceConfig"`: Defines the resource configuration for the data model in your Amplify
  project.
"""
function update_backend_api(
    appId,
    backendEnvironmentName,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api/$(backendEnvironmentName)",
        Dict{String,Any}("resourceName" => resourceName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_backend_api(
    appId,
    backendEnvironmentName,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/api/$(backendEnvironmentName)",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("resourceName" => resourceName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_backend_auth(app_id, backend_environment_name, resource_config, resource_name)
    update_backend_auth(app_id, backend_environment_name, resource_config, resource_name, params::Dict{String,<:Any})

Updates an existing backend authentication resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_config`: The resource configuration for this request object.
- `resource_name`: The name of this resource.

"""
function update_backend_auth(
    appId,
    backendEnvironmentName,
    resourceConfig,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/auth/$(backendEnvironmentName)",
        Dict{String,Any}(
            "resourceConfig" => resourceConfig, "resourceName" => resourceName
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_backend_auth(
    appId,
    backendEnvironmentName,
    resourceConfig,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/auth/$(backendEnvironmentName)",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "resourceConfig" => resourceConfig, "resourceName" => resourceName
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_backend_config(app_id)
    update_backend_config(app_id, params::Dict{String,<:Any})

Updates the AWS resources required to access the Amplify Admin UI.

# Arguments
- `app_id`: The app ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"loginAuthConfig"`: Describes the Amazon Cognito configuration for Admin UI access.
"""
function update_backend_config(appId; aws_config::AbstractAWSConfig=global_aws_config())
    return amplifybackend(
        "POST",
        "/backend/$(appId)/config/update";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_backend_config(
    appId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/config/update",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_backend_job(app_id, backend_environment_name, job_id)
    update_backend_job(app_id, backend_environment_name, job_id, params::Dict{String,<:Any})

Updates a specific job.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `job_id`: The ID for the job.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"operation"`: Filters the list of response objects to include only those with the
  specified operation name.
- `"status"`: Filters the list of response objects to include only those with the specified
  status.
"""
function update_backend_job(
    appId, backendEnvironmentName, jobId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/job/$(backendEnvironmentName)/$(jobId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_backend_job(
    appId,
    backendEnvironmentName,
    jobId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/job/$(backendEnvironmentName)/$(jobId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_backend_storage(app_id, backend_environment_name, resource_config, resource_name)
    update_backend_storage(app_id, backend_environment_name, resource_config, resource_name, params::Dict{String,<:Any})

Updates an existing backend storage resource.

# Arguments
- `app_id`: The app ID.
- `backend_environment_name`: The name of the backend environment.
- `resource_config`: The resource configuration for updating backend storage.
- `resource_name`: The name of the storage resource.

"""
function update_backend_storage(
    appId,
    backendEnvironmentName,
    resourceConfig,
    resourceName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/storage/$(backendEnvironmentName)",
        Dict{String,Any}(
            "resourceConfig" => resourceConfig, "resourceName" => resourceName
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_backend_storage(
    appId,
    backendEnvironmentName,
    resourceConfig,
    resourceName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return amplifybackend(
        "POST",
        "/backend/$(appId)/storage/$(backendEnvironmentName)",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "resourceConfig" => resourceConfig, "resourceName" => resourceName
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end


text:
using Dash, DashHtmlComponents, DashCoreComponents

app = dash()

app.layout = html_div() do
    html_h1("Hello Dash"),
    html_div("Dash: A web application framework for Julia"),
    dcc_graph(
        id = "example-graph-1",
        figure = (
            data = [
                (x = ["giraffes", "orangutans", "monkeys"], y = [20, 14, 23], type = "bar", name = "SF"),
                (x = ["giraffes", "orangutans", "monkeys"], y = [12, 18, 29], type = "bar", name = "Montreal"),
            ],
            layout = (title = "Dash Data Visualization", barmode="group")
        )
    )
end

run_server(app, "0.0.0.0", debug=true)

max_stars_repo_name: joelostblom/dash-docs

max_issues_repo_name: joelostblom/dash-docs

max_forks_repo_name: joelostblom/dash-docs


text:
include("./game.jl")

using Distributions: Dirichlet
using LinearAlgebra: normalize!
using StatsBase
using Sockets

## MCTS setting

const Setting = (
        MAX_SIMULATION = 800,
        T              = 1.,
        C              = √3,
        ϵ              = 0.35,
        α              = 0.3,
        max_parall     = 100,
        PORT           = 8877
        )

function makeClients()
    Clients = Channel{TCPSocket}(Setting.max_parall)
    @simd for i=1:Setting.max_parall
        client = connect(Setting.PORT)
        put!(Clients, client)
    end
    Clients
end

function closeClients(Clients::Channel{TCPSocket})
    while isready(Clients)
        client = take!(Clients)
        close(client)
    end
    nothing
end

mutable struct Node
    N::Int
    W::Float16
    P::Float16
    vloss::Int
    parent::Union{Node, Nothing}
    children::Dict{Integer, Node}
    action::Union{Int8, String}
    isLeaf::Bool
    function Node(action=false, parent=nothing, P=Float16(0))
        new(Int(0), Float16(0), Float16(P), Int(0), parent, Dict{Integer, Node}(), action, true)
    end
end

function Base.show(io::IO, self::Node)
    "print out the node"
    children = keys(self.children)
    parent = isnothing(self.parent) ? "root" : self.parent.action
    print(io, "Node(action: $(self.action), parent: $parent, $children, ")
    p = self.N >0 ? self.W/self.N : 0
    print(io, "N/W/Q/P/VL: $(self.N)/$(self.W)/$(p)/$(self.P)/$(self.vloss)\n")
end

function bestChild(self::Node)
    best_child = nothing
    best_score = -Inf
    for child in values(self.children)
        Q = child.N > 0 ? (child.W-child.vloss)/child.N : 0
        curr = Q + Setting.C*child.P*√(self.N) / (1+child.N)
        if curr > best_score
            best_score = curr
            best_child = child
        end
    end
    return best_child
end

function add_noise!(probs::Array{Float32}, validmoves::Array{Int8,1})
    " Add Dirichlet noise in the root node "
    dirch = rand(Dirichlet(length(validmoves), Setting.α))
    @inbounds @. probs[validmoves] = probs[validmoves] * (1-Setting.ϵ) + dirch *Setting.ϵ
    nothing
end

function expand(self::Node, probs::Array{Float32}, moves::Array{Int8})
    for child in moves
        self.children[child] = Node(child, self, probs[child])
    end
    self.isLeaf = false
end

mutable struct MCTS
    root::Union{Nothing, Node}
    leaves::Int
    Clients::Channel{TCPSocket}
    function MCTS()
        new(nothing, 1, makeClients())
    end
end

function Base.show(io::IO, self::MCTS)
    "print out the node"
    compact = get(io, :compact, false)
    if !compact
        showroot = isnothing(self.root) ? "nothing" : self.root.action
        print(io, "MCTS(", showroot, ", ", self.leaves, ")")
    end
end

function backpropgation(root::Union{Node, Nothing}, q::Float16)
    while !isnothing(root.parent)
        root.vloss -= 1
        root.W += q
        root = root.parent
    end
end

function predict(game::Game, invaMoves::Array{Int8}, Clients)
    client = take!(Clients)
    println(client, game.state)
    flush(client)
    message = readuntil(client, "\n")
    put!(Clients, client)
    probs, vals = eval(Meta.parse(message))
    !isempty(invaMoves) && @inbounds probs[invaMoves] .= 0.
    normalize!(probs, 1)
    return probs, vals
end

function root_add_noise(game::Game, self::MCTS)
    vaMoves = validMoves(game)
    probs, _ = predict(game, setdiff(ALL_MOVES[1], vaMoves), self.Clients)
    add_noise!(probs, vaMoves)
    expand(self.root, probs, vaMoves)
end

function search!(self::MCTS, initState::String)
    root = self.root
    game = Game(initState)
    # selection
    curr_player = game.nextPlayer
    root.N += 1
    while !root.isLeaf
        root = bestChild(root)
        place(game, root.action)
        root.N += 1; root.vloss +=1
        if !iszero(game.winner)
            backpropgation(root, Float16(game.winner*curr_player))
            break
        end
    end
    # expansion
    if iszero(game.winner)
        vaMoves = validMoves(game)
        #bottleneck
        @inbounds probs, q = predict(game, setdiff(ALL_MOVES[1], vaMoves), self.Clients)
        game = nothing
        self.leaves += -1+length(vaMoves)
        expand(root, probs, vaMoves)
        # backpropgation
        backpropgation(root, q)
    end
end

function (self::MCTS)(game::Game; test::Bool=false, counts::Int = Setting.MAX_SIMULATION)
    "return move, Pi"

    initState = game.state
    if isnothing(self.root)
        self.root = Node(initState)
    elseif @inbounds self.root.action == initState[1:end-1]
        for child in values(self.root.children)
            if @inbounds child.action == int(initState[end])
                self.root = child
                self.root.parent = nothing
                break
            end
        end
    end
    total = 0
    if self.leaves < 9
        root_add_noise(game, self)
        total += 1
    end
    while total < counts
        parall = min(self.leaves, counts-total, Setting.max_parall)
        @sync for i=1:parall
            @async search!(self, initState)
        end
        total += parall
    end

    moves = self.root.children
    Pi = zeros(Float32, 9)
    if test
        # choose the action from the current state with greatest N
        for i in keys(moves)
            @inbounds Pi[i] = moves[i].N
        end
        normalize!(Pi, 1)
        move = argmax(Pi)
    else
        for i in keys(moves)
            @inbounds Pi[i] = moves[i].N ^ (1. / Setting.T)
        end
        normalize!(Pi, 1)
        @inbounds move = sample(ALL_MOVES[1], Weights(Pi))
    end
    # cut off the subtree
    self.root = moves[move]
    self.root.action = "$(game.state)$move"
    self.root.parent = nothing
    return move, Pi
end


text:
@testset "parse!" begin

    using TensorCast: SizeDict, parse!, needview!

    ## case "rex"
    dd = SizeDict()
    ff = Any[]
    flat, getafix, negated = parse!(dd, nothing, [], [:(i:3), :(j:4) ]; allowranges=true, flags=ff)
    @test unique(ff) == [:assert]
    @test length(dd.dict) == 2
    @test dd.dict[:i] == 3
    @test flat == [:i, :j]

    ## simplest array
    dd = SizeDict()
    flat, getafix, negated = parse!(dd, :Z, [:i, :_, :j, 1, :(-k)], [])
    @test flat == [:i, :j, :k]
    @test getafix == [:, :_, :, 1, :]
    @test needview!(getafix)          # true because it contains 1
    @test getafix == [:, 1, :, 1, :]  # mutated by needview!
    @test_broken negated == [:k]
    @test dd.dict[:k] == :(size(Z, 5))

    ## outside and inside
    dd = SizeDict()
    flat, getafix, negated = parse!(dd, :X, [:a, :(b\-c), 9], [:k, :(-l)])
    @test flat == [:k, :l, :a, :b, :c]
    @test getafix == [:,:,9]
    @test needview!(getafix)
    @test_broken negated == [:l, :c]
    @test_broken dd.dict[:l] == :(size(first(X, 2)))

    ## outside and inside, reduction allowing ranges
    dd = SizeDict()
    flat, getafix, negated = parse!(dd, :Y, [:a, :(-b\c\e)], [:(k:10), :l], allowranges=true)
    @test dd.dict[:k] == 10
    @test dd.dict[ [:b, :c, :e] ] == :(size(Y, 2))

end
@testset "SizeDict" begin

    using TensorCast: SizeDict, sizeinfer, savesize!, MacroError

    dd = SizeDict()
    dd.dict[:a] = 3
    dd.dict[:b] = 4
    dd.dict[[:c,:d]] = 100

    @test_throws MacroError sizeinfer(dd, [:a, :b, :c, :d])

    dd.dict[:d] = 10

    ss = sizeinfer(dd, [:a, :b, :c, :d], nothing, true) # leave one :
    @test eval.(ss) == [3,4,:,10]

    ss = sizeinfer(dd, [:a, :b, :c, :d], nothing, false)
    @test eval.(ss) == [3,4,10,10]

    savesize!(dd, :a, 99)
    @test dd.dict[:a] == 3 # logic changed here, first value kept
    @test_throws DimensionMismatch eval.(dd.checks)

end
@testset "minus" begin

    using TensorCast: oddunique, stripminus!

    @test oddunique([:a, :b, :c]) == [:a, :b, :c]
    @test oddunique([:a, :b, :c, :a]) == [:b, :c]
    @test oddunique([:a, :b, :c, :a, :b]) == [:c]
    @test oddunique([:a, :b, :c, :a, :b, :a]) == [:a, :c]

    nn = []
    @test stripminus!(nn, :z) == :z
    @test stripminus!(nn, :(-z)) == :z
    @test nn == [:z]

    @test stripminus!(nn, :((a, b, -c))) == [:a, :b, :c]
    @test nn == [:z, :c]

    @test stripminus!(nn, :(a\b)) == [:a, :b]
    @test stripminus!(nn, :(a\-b\c)) == [:a, :b, :c]
    @test stripminus!(nn, :(-a\b\c\-d)) == [:a, :b, :c, :d]
    @test nn == [:z, :c, :b, :a, :d]

end


text:
module EvenTotalPayment

export Payment, even_total_payment, total_payment, total_interest, estimate_interest_rate

const Money = BigFloat  # Use Decimal?

struct Payment
    payment::Money
    principals::Vector{Money}
    interests::Vector{Money}
    unpaid_balances::Vector{Money}
end

total_payment(p::Payment) = p.payment * length(p.principals)
total_interest(p::Payment) = sum(p.interests)

function even_total_payment(loan::Float64, interest_rate::Float64, n_payments::Int)::Payment
    even_total_payment(Money(loan), BigFloat(interest_rate), n_payments)
end

#=

A: loan, k: interest rate, x: monthly/yearly payment, n: payment period

A1 = A - (x - A * k)
A2 = A1 - (x - A1 * k)
   = (A - (x - A * k)) - (x - (A - (x - A * k)) * k)
   = A * (1 + k)^2 - x * ((1 + k) + 1)
A3 = A2 - (x - A2 * k)
   = (A * (1 + k)^2 - x * ((1 + k) + 1)) - (x - (A * (1 + k)^2 - x * ((1 + k) + 1)) * k)
   = A * (1 + k)^3 - x * ((1 + k)^2 + (1 + k) + 1)
...
An = 0

⟹

x = A * (1 + k)^n / (Σ_{i=0}^{n - 1} (1 + k)^i)

=#

"""
- interest_rate: monthly/yearly interest rate
- n_payments: the period of repayment in months/years
"""
function even_total_payment(loan::Money, interest_rate::BigFloat, n_payments::Int)::Payment
    load_coeffs = [(1 + interest_rate) ^ i for i in 1:n_payments]
    interest_coeffs = cumsum([1.0; load_coeffs[1:(end - 1)]])

    payment = loan * load_coeffs[end] / interest_coeffs[end]
    unpaid_balances = @. loan * load_coeffs - payment * interest_coeffs
    interests = [loan; unpaid_balances[1:(end - 1)]] .* interest_rate
    principals = payment .- interests

    Payment(payment, principals, interests, unpaid_balances)
end

function estimate_interest_rate(
    loan::Float64, n_payments::Int, each_payment::Float64,
)::Union{Nothing, Float64}
    rate = estimate_interest_rate(Money(loan), n_payments, Money(each_payment))
    return isnothing(rate) ? nothing : Float64(rate)
end

function estimate_interest_rate(
    loan::Money, n_payments::Int, each_payment::Money,
)::Union{Nothing, BigFloat}
    @inline compute_payment(r::BigFloat) = even_total_payment(loan, r, n_payments).payment
    low = big(0.0)
    high = big(1.0)
    if compute_payment(low) > each_payment || compute_payment(high) < each_payment
        return nothing
    end

    while true
        mid = (low + high) / 2.0
        p = compute_payment(mid)
        if abs(p - each_payment) < 0.01
            return mid
        end

        if p < each_payment
            low = mid
        else
            high = mid
        end
    end
end

end # module

max_stars_repo_name: gyk/TrivialSolutions

max_issues_repo_name: gyk/TrivialSolutions

max_forks_repo_name: gyk/TrivialSolutions


text:
## Annotation

struct Annotation
    jann::JAnnotation
end

# TODO: make more meaningful show
Base.show(io::IO, ann::Annotation) = print(io, "Annotation(...)")

function Annotation(text::AbstractString)
    jann = JAnnotation((JString,), text)
    return Annotation(jann)
end

## StanfordCoreNLP

struct StanfordCoreNLP
    jpipeline::JStanfordCoreNLP
end

Base.show(io::IO, pipeline::StanfordCoreNLP) = print(io, "StanfordCoreNLP(...)")

function StanfordCoreNLP(props::Dict{String, String})
    jprops = to_jprops(props)
    jpipeline = JStanfordCoreNLP((JProperties,), jprops)
    return StanfordCoreNLP(jpipeline)
end

function annotate!(pipeline::StanfordCoreNLP, doc::Annotation)
    jcall(pipeline.jpipeline, "annotate", Void, (JAnnotation,), doc.jann)
end


text:
@testset "Segregating sites" begin

    S = [dna"aatcga", dna"aaa", dna"tatcg", dna"catcgac", dna"aatc"]
    @test count(Segregating, S)[1] == 2 && count(Segregating, S)[2] == 3

    S = [dna"ATAATAAAAAAATAATAAAAAAATAAAAAAAATAAAAAAAA",
         dna"AAAAAAAATAAATAATAAAAAAATAAAAAAAAAAAAAAAAA",
         dna"AAAATAAAAATATAATAAAAAAATATAAAAAAAAAAAAAAA",
         dna"AAAAAAAAAAAATAATAAAAAAATAAATAAATAAAAAAAAA",
         dna"AAAATAAAAAAAATATAAAAAAATAAAAAAAAAAAAAAAAA",
         dna"AAAATAAAAAAAAAATAAAAAAAAAAAAAAAAAAATAAAAA",
         dna"AAAAAATAAAAATAATAAAAAAATAAAAAAAAAAAAAAAAA",
         dna"AAAAAAAAAAAAAAATAAAAAAATAAAAAAAAAAAAAAATA",
         dna"AAAAAAAAAAAAAAAAAAAAAAATAAAAAAAAAAAAAAAAA",
         dna"AAAAAAAAAAAAAAATAAAAAAATAATAAAAAAAAAAAAAA"]
    @test count(Segregating, S)[1] == 16 && count(Segregating, S)[2] == 41

end


text:
#=
Test images for cmocean colormaps.

The design of these images is described in Kovesi (2015),
and illustrated in Figure 2.

https://arxiv.org/abs/1509.03700

<summary>
The wavelength of the sine wave is 8px, with an image width of 512px.
On a monitor with a nominal pixel pitch of 0.25mm this gives a physical
wavelength of 2mm. At a viewing distance of 600mm this correspondes to
0.19 deg, or 5.2 cycles / degree. This falls within the range of spatial
frequencies (3-7 cycles / degree) at which most people have maimal contrast
sensitivity to a sine wave grating. A wavelength of 8px also provides a
reasonable discrete representation of a sine wave.

The sine wave amplitude increases with the square of the distance from
the bottom of this image.

Each row of the test image is normalised so that it spans a range of
0 to 255. This means that the underlying ramp at the top of the image
will be reduced in slope slightly to accommodate the sine wave.
</summary>

=#

using PyPlot
include("cmocean.jl")

data = zeros(51,512)

for row in 1:51
	A = 511 * 0.05 * ( (51-row)/50 )^2
	for col in 1:512
		x = col - 1
		data[row,col] = x + A * sin(x * 2pi / 8)
	end
	#
	# Renormalize row.
	#
	ymax = maximum(data[row,:])
	ymin = minimum(data[row,:])

	data[row,:] = (data[row,:] - ymin) * 255 / (ymax - ymin)
end

##################################################
#
#
figure(1)
clf()
plot(data[1,:], "C0-")

##################################################
#
#
figure(2, figsize=(10,10))
clf()

labels = ["algae", "amp", "balance", "curl", "deep", "delta",
		"dense", "gray", "haline", "ice", "matter", "oxy",
		"phase", "solar", "speed", "tempo", "thermal", "turbid"]

for j in 1:9
	for k in [2j-1, 2j]
		subplot(9,2,k)
		title(labels[k])
		imshow(data, cmap=labels[k])
		xticks([])
		yticks([])
	end
end

##################################################
#
# Compare some colormaps from cmocean vs matplotlib.
#
figure(3, figsize=(10,10))
clf()

labels = [
	"jet"		"phase"
	"winter"	"haline"
	"YlGn"		"speed"
	"Blues"		"ice"
	"hot"		"solar"
	"Greens"	"algae"
	"BuPu"		"dense"
	"coolwarm"	"balance"
]
N = size(labels,1)

for j in 1:N
	for k in [1,2]
		subplot(N,2,2j+1-k)
		title(labels[j,k])
		imshow(data, cmap=labels[j,k])
		xticks([])
		yticks([])
	end
end


text:
using Images
using Colors
using MAT
using YAML

abstract FaceDataset

include("utils.jl")
include("ck.jl")
include("cootes.jl")
include("kaggle_fer.jl")
include("put.jl")


text:
#
# Load packages and functions
include("../src/init.jl")
include("../src/fct.jl")
# include("../src/worker_fct.jl")

calib_filepath = "../dicts/calib.json"
calib = JSON.parsefile(calib_filepath);

datasets_str = [
    "0053-0064",
    "0065-0079",
    "0080-0092",
    "0093-0113"
]
det_lib = JSON.parsefile("../dicts/det_lib.json");
bl_dict = JSON.parsefile("../dicts/bl_rms_limits.json");
parameters = JSON.parsefile("../dicts/electronics_parameters.json")

#
# Output paths and filter settings
plots_base_path = "../../waveforms/sim/plots/"
base_path_raw   = "../../../2020-02-06_8380701d_st_ffischer/pulses/sim/raw_0vbb/"
base_path       = "../../waveforms/sim/0vbb_check/"
plots_bl_path   = "../../waveforms/baselines/plots/"
base_bl_path    = "../../waveforms/baselines/wf/"

sampling_time   = 1u"ns";

channels = []
for ch in 17:1:36
    if channel_to_bege[ch] == false || ch in [5,6,7,13]
        continue
    end
    push!(channels, ch)
end
println(channels)
for ch in channels
    Base.run(`clear`)
    ds_str = det_lib[channel_to_name[ch]]["run_str"]

    str_ch = lpad(ch, 2, "0");
    @info("Start Ch$str_ch | " * channel_to_name[ch])
    @info(">---------------------------------------------------------------<")
    @info("Read in baselines")
    bl_files = glob(joinpath(base_bl_path, "*/" * str_ch*"-"*channel_to_name[ch]*"/*.h5"))
    filtered = []
    for file in bl_files
        run = parse(Int64, split(split(basename(file), "-")[2], "run")[end])
        if run in calib[channel_to_name[ch]]["data"][ds_str]["used_runs"]
            push!(filtered, file)
        end
    end
    bl_files = filtered

    bl = Table(run = [], datasetID = [], waveform = [])
    @showprogress 1 "Filtering baselines for Ch$str_ch ..." for file in bl_files
        tmp_data = HDF5.h5open(file, "r") do h5f
            LegendHDF5IO.readdata(h5f, "data")
        end
        tmp_data = tmp_data |> @filter(bl_dict[channel_to_name[ch]]["low_rms_limit"] < rms(_.waveform.value) < bl_dict[channel_to_name[ch]]["high_rms_limit"]) |> Table
        if size(tmp_data,1) > 0
            append!(bl, Table(run = tmp_data.run, datasetID = tmp_data.datasetID, waveform = tmp_data.waveform))
        end
    end

    bl = bl |> @filter(bl_dict[channel_to_name[ch]]["low_rms_limit"] < rms(_.waveform.value) < bl_dict[channel_to_name[ch]]["high_rms_limit"]) |> Table
    @info("Number of baselines: " * string(size(bl,1)))

    @info(">---------------------------------------------------------------<")
    files = glob(joinpath(base_path_raw, string(ch) * "-" * channel_to_name[ch] * "/*w_filter*.h5"));
    number_of_pulses = 0;
    key_str = []
    for file in files
        push!(key_str, split(basename(file), "_evts_")[1])
    end
    key_str = unique(key_str)
    for k in key_str
        last_file = basename(glob(joinpath(base_path_raw, string(ch) * "-" * channel_to_name[ch] * "/" * string(k) * "*.h5"))[end])
        number_of_pulses += parse(Int64, split(split(last_file, "_evts_")[2], "-")[end])
    end
    @info("Found number of simulation pulses: " * string(number_of_pulses))
    @info("Found number of noise baselines: " * string(size(bl,1)))
    # get first_range
    if number_of_pulses <= size(bl,1)
        first_range = [1]
    else
        mult_factor = ceil(number_of_pulses/size(bl,1))
        first = 1
        last = 201
        step = Int(round((last-first)/(mult_factor)))
        first_range = first:step:last
    end
    @info("This results in " * string( size(bl, 1) * length(first_range) ) * " baselines for " * string(number_of_pulses) * " pulses")
    @info(">---------------------------------------------------------------<")
    @info("Indexing the baselines")
#     indices = Table(bl=[], first=[])
#     for i in 0:1:number_of_pulses
#         bl_id = i%size(bl,1) + 1
#         first = first_range[Int(ceil((i + 1) / size(bl,1)))]
#         append!(indices, Table(bl=[bl_id], first=[first]))
#     end
    indices = []
    for i in 0:1:(size(bl, 1) * length(first_range)-1)
        bl_id = i%size(bl,1) + 1
        first = first_range[Int(ceil((i+1) / size(bl,1)))]
        push!(indices, [bl_id, first])
    end
    indices = shuffle(indices)
    pulse_id = 1
    @info("Add baselines to pulses")

    @showprogress "Adding baselines..." for file in files
        create_file = false
        ch_str = lpad(ch, 2, "0");
        filename = joinpath(joinpath(base_path, str_ch * "-" * channel_to_name[ch]), basename(file))
        !isdir(dirname(filename)) ? mkpath(dirname(filename)) : ""
        if isfile(filename)
            if stat(filename).size <= stat(file).size/2
                create_file = true
            end
        else
            create_file = true
        end
        if create_file
            data_w_bl = Table(energy=[], multiplicity=[], timestamp=[], run=[], channel=[], waveform=[], evtno=[], pos=[])
            file_no_filter = joinpath(dirname(file), split(basename(file), "w_filter")[1] * "w_bl" * split(basename(file), "w_filter")[end])

            data = HDF5.h5open(file, "r") do h5f
                LegendHDF5IO.readdata(h5f, "data")
            end
            data_no_filter = HDF5.h5open(file_no_filter, "r") do h5f
                LegendHDF5IO.readdata(h5f, "data")
            end

            for i in eachindex(data)
                event = data[i]
                time = event.waveform.time
                pulse = event.waveform.value ./ get_avg_maximum(event.waveform.value, 10)
                pulse .*= sum(event.energy).val #* 1000 # Energy is stored in MeV

                bl_id = indices[pulse_id][1]
                first = indices[pulse_id][2]

                last = first + length(pulse) - 1
                pulse .+= bl[bl_id].waveform.value[first:1:last]
    #             return plot(RDWaveform(time, pulse))
                append!(data_w_bl, Table(energy=[event.energy],
                                        multiplicity=[event.multiplicity],
                                        timestamp=[event.timestamp],
                                        run=[event.run],
                                        channel=[event.channel],
                                        waveform=[RDWaveform(time, pulse)],
                                        evtno=[data_no_filter[i].evtno],
                                        pos=[data_no_filter[i].pos])
                    );
                pulse_id += 1
            end
            HDF5.h5open(filename, "w") do h5f
                LegendHDF5IO.writedata(h5f, "data", Table(energy     = VectorOfArrays(Array{typeof(data_w_bl[1].energy),1}(data_w_bl.energy)),
                                                        multiplicity = Int32.(data_w_bl.multiplicity),
                                                        timestamp    = Int32.(data_w_bl.timestamp),
                                                        run          = Int32.(data_w_bl.run),
                                                        channel      = Int32.(data_w_bl.channel),
                                                        waveform     = ArrayOfRDWaveforms( Array{typeof(data_w_bl[1].waveform), 1}(data_w_bl.waveform) ),
                                                        evtno        = Int32.(data_w_bl.evtno),
                                                        pos          = VectorOfArrays(Array{typeof(data_w_bl[1].pos), 1}(data_w_bl.pos)),
                        ))
            end
        else
            pulse_id += size(HDF5.h5open(file, "r") do h5f
                LegendHDF5IO.readdata(h5f, "data")
            end, 1)
        end
    end
end

max_stars_repo_path: calib/simPrep - add baselines to 0vbb.jl


text:
module PrincipalMomentAnalysis

using LinearAlgebra
using SparseArrays
using Statistics
using NearestNeighbors

include("svd.jl")
include("simplices.jl")
include("pma.jl")
include("util.jl")

export
	PMA,
	pma,
	SimplexGraph,
	groupsimplices,
	timeseriessimplices,
	neighborsimplices,
	normalizemean!,
	normalizemean,
	normalizemeanstd!,
	normalizemeanstd

end


text:
function MathProgSolverInterface.initialize(d::MDP, rf::Vector{Symbol})
    for feat in rf
        if !(feat in [:Grad, :Jac, :Hess])
            error("Unsupported feature $feat")
            # TODO: implement Jac-vec and Hess-vec products
            # for solvers that need them
        end
    end
end

MathProgSolverInterface.features_available(d::MDP) = [:Grad, :Jac, :Hess]
MathProgSolverInterface.eval_f(d::MDP, u) = Divergences.evaluate(d.div, u[1:d.nobs])

function MathProgSolverInterface.eval_g(d::MDP, g, u)
  n = d.nobs
  k = d.npar
  m = d.nmom
  θ   = u[(n+1):(n+k)]
  p   = u[1:n]
  @inbounds g[1:m]  = d.momf.sn(θ, p)
  @inbounds g[m+1]  = sum(p)
end

function MathProgSolverInterface.eval_grad_f(d::MDP, grad_f, u)
  n = d.nobs
  k = d.npar
  m = d.nmom

  for j=1:n
    @inbounds grad_f[j] = Divergences.gradient(d.div, u[j])
  end
  for j=(n+1):(n+k)
    @inbounds grad_f[j] = 0.0
  end
end

function MathProgSolverInterface.jac_structure(d::MDP)
  n = d.nobs
  k = d.npar
  m = d.nmom

  rows = Array(Int64, d.gele)
  cols = Array(Int64, d.gele)
  for j = 1:m+1, r = 1:n+k
        if !((r > n) && (j==m+1))
          @inbounds rows[r+(j-1)*(n+k)] = j
          @inbounds cols[r+(j-1)*(n+k)] = r
        end
      end
  rows, cols
end

function MathProgSolverInterface.hesslag_structure(d::MDP)
  n = d.nobs
  k = d.npar
  m = d.nmom

  rows = Array(Int64, d.hele)
  cols = Array(Int64, d.hele)
  for j = 1:n
    @inbounds rows[j] = j
    @inbounds cols[j] = j
  end
  idx = n+1

  for s = 1:n
    for j = 1:k
      @inbounds rows[idx] = n+j
      @inbounds cols[idx] = s
      idx += 1
    end
  end

  for j = 1:k
    for s = 1:j
      @inbounds rows[idx] = n+j
      @inbounds cols[idx] = n+s
      idx += 1
    end
  end
  rows, cols
end

function MathProgSolverInterface.eval_jac_g(d::MDP, J, u)
 n = d.nobs
 k = d.npar
 m = d.nmom

 global __p    = u[1:n]
 θ      = u[(n+1):(n+k)]
 g      = d.momf.sᵢ(θ)
 ∂∑pᵢsᵢ = d.momf.∂∑pᵢsᵢ(θ)

 for j=1:m+1, i=1:n+k
  if(j<=m && i<=n)
    @inbounds J[i+(j-1)*(n+k)] = g[i+(j-1)*n]
  elseif (j<=m && i>n)
    @inbounds J[i+(j-1)*(n+k)] = ∂∑pᵢsᵢ[j, i-n]
  elseif (j>m && i<=n)
    @inbounds J[i+(j-1)*(n+k)] = 1.0
  end
end
end

function MathProgSolverInterface.eval_hesslag(d::MDP, H, u, σ, λ)
  n = d.nobs
  k = d.npar
  m = d.nmom

  global __p  = u[1:n]
  global __λ  = λ[1:m]
  θ           = u[(n+1):(n+k)]

  ∂sᵢλ = transpose(d.momf.∂sᵢλ(θ))

  if σ==0
    for j=1:n
      @inbounds H[j] = 0.0
    end
  else
    for j=1:n
      @inbounds H[j] = σ*Divergences.hessian(d.div, u[j])
    end
  end
  @inbounds H[n+1:n*k+n] = ∂sᵢλ[:]
  @inbounds H[n*k+n+1:d.hele] = gettril(d.momf.∂²sᵢλ(θ))
end

function mdtest(mf::MomentFunction,
                div::Divergence,
                θ₀::Vector,
                lb::Vector, ub::Vector;
                solver=IpoptSolver())

    model = MathProgSolverInterface.model(solver)

    m = mf.nmom
    n = mf.nobs
    k = mf.npar

    u₀ = [ones(n), θ₀]

    gele = int((n+k)*(m+1)-k)
    hele = int(n*k + n + (k+1)*k/2)

    # lb = [-2., -2]
    # ub = [2, 2.]
    g_L = [zeros(m), n];
    g_U = [zeros(m), n];

    u_L = [zeros(n),  lb];
    u_U = [ones(n)*n, ub];
    # l = [1,1,1,1]
    # u = [5,5,5,5]
    # lb = [25, 40]
    # ub = [Inf, 40]
    MdProb = MinimumDivergenceProblem(mf, div, n, m, k, gele, hele, Array(Float64, n), Array(Float64, m+1))

    MathProgSolverInterface.loadnonlinearproblem!(model, n+k, m+1, u_L, u_U, g_L, g_U, :Min, MdProb)

    MathProgSolverInterface.setwarmstart!(model, u₀)

    MathProgSolverInterface.optimize!(model)
    stat = MathProgSolverInterface.status(model)

    # @test stat == :Optimal
    uᵒ = MathProgSolverInterface.getsolution(model)
    Qᵒ = MathProgSolverInterface.getobjval(model)
    (MathProgSolverInterface, uᵒ, Qᵒ)

end


text:
function main()
	user_input = ""
	while user_input != "exit"
		print("Input text: \n")
		user_input = readline()
		print(user_input * "\n")
	end
end

function listen()
end

function respond()
end

main()

max_stars_repo_name: seantfish/chatbot

max_issues_repo_name: seantfish/chatbot

max_forks_repo_name: seantfish/chatbot


text:
#NOTE: Uncomment below bloc for stand alone testing
#WARNING WARNING WARNING don't for get to comment include("test.jl") in Finometics.jl
using Revise

#=include("Finometrics.jl")
using Distributions, LinearAlgebra, #=CUDA, =#DataFrames,
 Dates, DataFrames, GLM, Random
Random.seed!(11)
import Base: +, -, ==, >, <, ≥, ≤, length, isless, isequal
import StatsModels: implicit_intercept

const MFloat64 = Union{Float64, Missing}
#include("Finometrics.jl")
using Revise
const FMExpr = Union{Symbol,Expr,Nothing}

macro mpar(cond, expr)
  quote
    if $(esc(cond))
        :($(Threads.@threads($expr)))
    else
        :($($expr))
    end
  end
end=#

#NOTE: End stand-alone comment block

function testMM(df::DataFrame, loops=1)
  #println(df)
  m = Finometrics.generateX(Matrix{Float64}, df, :(x+y+f))

  (loops==1) && display(m)

  return m
end

function testMM(loops::Int; N::Int=1000, G::Int=50)
  local tot::Float64 = 0.0
  @info "testing MM. Failure will result in an error."

  df = DataFrame(x = 1001:(1000+N), y = rand(N), z=rand(N),
    f = (i->Symbol(:q,i÷(N ÷ G))).(1:N))

  @time for i ∈ 1:loops
    m=testMM(df, loops)
    (sum(df.x .≠ m[:,2]) == 0) || error("Invalid x column! df.x:$(df.x)\n###\nm[:,2]:$(m[:,2])")
    (sum(df.y .≠ m[:,3]) == 0) || error("Invalid y column!")
    (sum(1 .≠ m[:,1]) == 0) || error("Invalid intercept column!")
    (size(m,1) == N) || error("Invalid row dimension!")
    (size(m,2) == length(unique(df.f))+2) || error(
      "Invalid column dimension! Effects=$(length(unique(df.f))) size=$(size(m))")
  end

  println(tot)
end

#use this to test the lag functions
function testlaganddifference(N = 10_000)
  rowindex = collect(1:N)
  periodcol = deepcopy(rowindex)

  @info "testing lag and difference. Failure will result in an error."

  #make a test frame
  df = DataFrame(rowindex=rowindex, period = periodcol, group1 = periodcol .÷ 17,
    group2 = periodcol .÷ 29, target1 = rand(N), target2 = rand(N))

  #sort!(df, [:group1, :period, :group2])
  #CASE 1: create lagged field Lgroup1
  Finometrics.lagwithin!(df, :target1, :group1, :period)

  #CASE 2: create lagged fields L2target1 and L2target2
  sort!(df, [:group1, :group2])
  Finometrics.lagwithin!(df, [:target1, :target2], [:group1, :group2], :period, lags=2)

  #CASE 3: difference :Ltarget1 and create DLtarget1 and LLtarget1
  Finometrics.differencewithin!(df, :Ltarget1, :group1, :period, deletelag=false,
    laggedname=:LLtarget1e, differencedname=:DLtarget1e)

  #CASE 4: difference [:L2target1, :L2target2] creating
  # [:DL2target1e, :DL2target2e], [:LL2target1e, :LL2target2e]
  Finometrics.differencewithin!(df, [:L2target1, :L2target2], [:group1, :group2], :period,
    deletelag=false, differencednames=[:DL2target1e, :DL2target2e],
    laggednames = [:LL2target1e, :LL2target2e])

  #validation for cases 1 and 3
  sort!(df, [:group1, :period])
  for subdf ∈ groupby(df, :group1)
    sN::Int = size(subdf, 1)
    for r ∈ 1:sN
      if r > 1 #CASE 1check
        @assert subdf[r-1, :target1] == subdf[r, :Ltarget1]
      else
        @assert ismissing(subdf[r, :Ltarget1])
      end

      if r > 2 #CASE 3 check
        @assert subdf[r-1, :Ltarget1] == subdf[r, :LLtarget1e]
        @assert subdf[r, :Ltarget1] - subdf[r, :LLtarget1e] == subdf[r, :DLtarget1e]
      else
        @assert ismissing(subdf[r, :LLtarget1e])
        @assert ismissing(subdf[r, :DLtarget1e])

      end
    end
  end

  #validation for cases 2 and 4
  sort!(df, [:group1, :group2, :period])
  for subdf ∈ groupby(df, [:group1, :group2])
    sN::Int = size(subdf, 1)
    for r ∈ 1:sN
      if r > 2 #CASE 2 check
        @assert subdf[r-2, :target1] == subdf[r, :L2target1]
        @assert subdf[r-2, :target2] == subdf[r, :L2target2]
      else
        @assert ismissing(subdf[r, :L2target1])
        @assert ismissing(subdf[r, :L2target2])
      end

      if r > 3 #CASE 4 check
        @assert subdf[r-1, :L2target1] == subdf[r, :LL2target1e]
        @assert subdf[r-1, :L2target2] == subdf[r, :LL2target2e]
        @assert subdf[r, :L2target1] - subdf[r, :LL2target1e] == subdf[r, :DL2target1e]
        @assert subdf[r, :L2target2] - subdf[r, :LL2target2e] == subdf[r, :DL2target2e]
      else
        @assert ismissing(subdf[r, :LL2target1e])
        @assert ismissing(subdf[r, :LL2target2e])
        @assert ismissing(subdf[r, :DL2target1e])
        @assert ismissing(subdf[r, :DL2target2e])

      end
    end
  end

  display(df)
end

function testYearQuarter()

  @info "testing year quarter. Failure will result in an error."
  #test the first constructor
  yq1::Finometrics.YearQuarter = Finometrics.YearQuarter(1998,2)
  try
    YearQuarter(1985,7)
    @assert false
  catch err
    (typeof(err)<:AssertionError) && error("Error catching invalid values in first constructor")
  end

  #test the second constructor
  yq2::Finometrics.YearQuarter = Finometrics.YearQuarter(2000.4)
  try
    Finometrics.YearQuarter(2000.05)
    @assert false
  catch err
    (typeof(err)<:AssertionError) && error("Error catching invalid values in 2nd constructor")
  end

  #test addition of quarters
  for i ∈ 0:10
    @assert (yq1 + i) == (yq2 - (10-i))
  end
  #@assert yq1 + 10 == yq2
  #@assert yq2 - 10 == yq1

  @assert yq2 - yq1 == 10
  @assert yq1 < yq2
  @assert yq2 > yq1
  @assert yq2 ≥ yq1
  @assert yq1 ≥ yq1

  #println(yq1)
  #println(Float64(yq1))
end

function testYearMonth()
  @info "testing year month. Failure will result in an error."
  #test the first constructor
  ym1::Finometrics.YearMonth = Finometrics.YearMonth(1998,2)
  try
    Finometrics.YearMonth(1985,14)
    @assert false
  catch err
    (typeof(err)<:AssertionError) && error("Error catching invalid values in first constructor")
  end

  #test the second constructor
  ym2::Finometrics.YearMonth = Finometrics.YearMonth(2008_04)
  try
    Finometrics.YearMonth(2000_14)
    @assert false
  catch err
    (typeof(err)<:AssertionError) && error("Error catching invalid values in 2nd constructor")
  end

  #test addition of quarters
  for i ∈ 0:122
    @assert (ym1 + i) == (ym2 - (122-i))
  end

  @assert ym2 - ym1 == 122
  @assert ym1 < ym2
  @assert ym2 > ym1
  @assert ym2 ≥ ym1
  @assert ym1 ≥ ym1

end

function LMtest(::Type{M}=Matrix{Float64}, ::Type{V}=Vector{Float64};
    N::Int = 200, K::Int = 2, testerrors::Bool = true,
    qrtype::Type = M, iter::Int = 1, testprimarywithin::Bool = false, runslow::Bool = true) where {
    M<:AbstractMatrix, V<:AbstractVector}

  @warn "Testing LM. Most tests are automated at this point but
    some tests, like cluster equivelency, are manual. Generally though, for a quick look
    a lack of error should indicate nothing horrific is going on."
  local lin::Finometrics.FMLM

  #Allocate
  X::M = M(undef, N,K)
  Y::V = V(undef, N)
  ε::V = similar(Y)

  #parameters for the simulation
  σ2::Vector{Float64} = [2.0^2.0 for i::Int ∈ 1:N]
  σ2[1:ceil(Int, N/2)] .= 0.5^2.0
  β::V = [(1.0 * i) for i::Int ∈ 1:K]
  #println("β: ", β)
  #println("σ2: $σ2")

  #this will hold the sampled beta
  e::Vector{Float64} = similar(ε)

  #run the simulation
  for i ∈ 1:K
    X[:,i] .= V(rand(Uniform(),N))
  end

  ε = ((s2::Float64)->rand(Normal(0.0,s2^0.5))).(σ2)
  Y =  X*β .+ ε

  df::DataFrame = DataFrame(idx = 1:N)
  xnames = (i->Symbol(:X,i)).(1:K)

  for (i,x) ∈ enumerate(eachcol(X))
    df[!, xnames[i]] = x
  end
  df.Y = Y
  df.G = (i->Symbol(:G,i)).(rand(1:5,N))
  df.C1 = (i->Symbol(:C,i)).((j->j÷10).(1:N))
  df.C2 = (i->Symbol(:C,i)).((j->j%10).(1:N))

  #get the linear model
  xspec = Meta.parse(join((string).(xnames),"+"))

  println("minimal test")
  Finometrics.FMLM(df, xspec, :Y, containsmissings=false)

  print("Time running primary regression...")
  @time for i ∈ 1:iter
    lin = Finometrics.FMLM(df, xspec, :Y, M, V, #withinsym=:C1,
      clustersyms=:C1, qrtype=qrtype, checkwithin=testprimarywithin, containsmissings=false)
  end

  if testerrors
    #get the homoskedastic SEs
    ΣHomosked::Matrix{Float64} = Finometrics.homoskedasticΣ!(lin)
    runslow && (ΣHomoskedSlow::Matrix{Float64} = Finometrics.homoskedasticΣslow(lin))

    #print the coefficients
    println("\nCoefficients: ",lin.β)
    modelcoef = ((lin.X' * lin.X)\I) * lin.X' * lin.Y
    println("Model coeff: ", modelcoef)
    @assert modelcoef ≈ lin.β
    A::Matrix{Float64} = [ones(N) df.X1 df.X2 df.X3 df.X4 df.X5]
    manualcoef = ((A' * A)\I) * A' * Y
    @assert manualcoef ≈ lin.β
    println("Manual coef:", manualcoef)
    @info "passed coefficient test"

    xnamesfixed = [xnames; :G]
    xspecfixed = Meta.parse(join((string).(xnamesfixed),"+"))
    linfixed = Finometrics.FMLM(df, xspecfixed, :Y, M, V, #withinsym=:C1,
      clustersyms=[:C1, :C2], qrtype=qrtype, checkwithin=testprimarywithin, containsmissings=false)
    xspecwithin = Meta.parse("$(join((string).(xnames),"+")) + 0")
    linwithin::Finometrics.FMLM = Finometrics.FMLM(df, xspecwithin, :Y, M, V, withinsym=:G,
      clustersyms=[:C1, :C2], checkwithin=true, qrtype=qrtype)
    ΣHomoskedfixed::Matrix{Float64} = Finometrics.homoskedasticΣ!(linfixed)
    ΣHomoskedwithin::Matrix{Float64} = Finometrics.homoskedasticΣ!(linwithin)

    println("Coefficients (fixed G): ",linfixed.β)
    println("Coefficients (w/in G): ",linwithin.β)
    @assert linwithin.β ≈ linfixed.β[2:(K+1)]
    @info "passed coefficients fixed effect vs within test"

    homoskederr = diag(ΣHomosked).^.5
    homoskederrslow = diag(ΣHomoskedSlow).^.5
    println("\nHomoskedastic Errors: ", homoskederr)
    runslow && println("Check: ", homoskederrslow)
    runslow && (@assert homoskederr ≈ homoskederrslow)
    runslow && @info "passed homosked test"

    homoskederrfixed = diag(ΣHomoskedfixed)[2:(1+K)].^.5
    homoskederrwithin = diag(ΣHomoskedwithin).^.5
    println("Homoskedastic Errors (fixed): ", homoskederrfixed)
    println("Homoskedastic Errors (w/in): ", homoskederrwithin)
    @assert homoskederrfixed ≈ homoskederrwithin
    @info "passed homosked fixed effects vs within test"

    @info "check for warnings if intercept + within"
    linwithin = Finometrics.FMLM(df, xspec, :Y, M, V, withinsym=:G,
      clustersyms=[:C1, :C2], checkwithin=true, qrtype=qrtype)

    #get the modified white SEs
    ΣMWhite::Matrix{Float64} = similar(ΣHomosked)
    Finometrics.modifiedwhiteΣ!(lin, ΣMWhite)
    runslow && (ΣMWhiteSlow::Matrix{Float64} = Finometrics.modifiedwhiteΣslow(lin))

    #print the coefficients
    println("\nModified White Errors: ",diag(ΣMWhite).^.5)
    runslow && println("Check: ", diag(ΣMWhiteSlow).^.5)
    runslow && (@assert diag(ΣMWhite).^.5 ≈ diag(ΣMWhiteSlow).^.5)
    runslow && @info "passed MWhite test"

    #get the white SEs
    ΣWhite::Matrix{Float64} = similar(ΣHomosked)
    Finometrics.whiteΣ!(lin, ΣWhite)
    runslow && (ΣWhiteSlow::Matrix{Float64} = Finometrics.whiteΣslow(lin))

    #print the coefficients
    println("\nWhite Errors: ",diag(ΣWhite).^.5)
    runslow && println("Check: ", diag(ΣWhiteSlow).^.5)
    runslow && (@assert diag(ΣWhite).^.5 ≈ diag(ΣWhiteSlow).^.5)
    runslow && @info "passed white error test"

    #get the modified white SEs
    Σclustered::Matrix{Float64} = similar(ΣHomosked)
    Finometrics.clusteredΣ!(lin, Σclustered)
    ΣclusteredChk =Finometrics.clusteredΣ!(linwithin, Σclustered) #might need a better check here
    println("\nClustered Errors: ",diag(Σclustered).^.5)
    println("Check: ", diag(ΣclusteredChk ).^.5)
    @assert diag(Σclustered).^.5 ≈ diag(ΣclusteredChk ).^.5
    @info "passed cluster error test"

    linalt2 = Finometrics.FMLM(df, xspecwithin, :Y, M, V, withinsym=:G,
      clustersyms=[:C1,:C2], qrtype=qrtype, checkwithin=testprimarywithin, containsmissings=false)
    Σwithinclustered::M = M(undef, linalt2.K, linalt2.K)
    Finometrics.clusteredΣ!(linalt2, Σwithinclustered, clusters = [linalt2.clusters[1]], testequivelance=true)
    Finometrics.clusteredΣ!(linalt2, Σwithinclustered, testequivelance=true)
    @info "passsed cluster method equivelance test"

    #get the nw SEs
    ΣNW::Matrix{Float64} = similar(ΣHomosked)
    Finometrics.neweywestΣ!(lin, 3, ΣNW)
    runslow && (ΣNWSlow::Matrix{Float64} = Finometrics.neweywestΣslow(lin, 3))

    #print the coefficients
    println("\nNW Errors: ",diag(ΣNW).^.5)
    runslow && println("Check: ", diag(ΣNWSlow).^.5)
    runslow && @assert diag(ΣNW).^.5 ≈ diag(ΣNWSlow).^.5
    runslow && @info "passed newey west test"

    #get the nw SEs
    ΣNWpanel::Matrix{Float64} = similar(ΣHomosked)
    Finometrics.neweywestpanelΣ!(lin, 3, ΣNWpanel)
    runslow && (ΣNWpanelslow::Matrix{Float64} = Finometrics.neweywestpanelΣslow!(lin, 3))

    #print the coefficients
    println("\nNW panel Errors: ",diag(ΣNWpanel).^.5)
    runslow && println("Check: ", diag(ΣNWpanelslow).^.5)
    runslow && diag(ΣNWpanel).^.5 ≈ diag(ΣNWpanelslow).^.5
    runslow && @info "passed newey west panel test"

    SST::Float64 = sum((lin.Y .- mean(lin.Y)).^2)
    SSE::Float64 = sum(lin.ε.^2)

    println("\nR²: $(Finometrics.R²(lin)) R²-derived: $(1 - SSE/SST)")
    @assert Finometrics.R²(lin) ≈ 1 - SSE/SST
    @info "passed R² test"

    #test the project routines
    Pa::V = V(undef, N)
    Finometrics.project!(X,Pa)
    println("\nP: ", Pa[1:5])
    if N≤10_000 #only run on small samples or we will run out of memory
      PM::M = M(undef, N,N)
      runslow && (PS::M = M(undef, N,N))

      Finometrics.project!(X,PM)
      runslow && Finometrics.projectslow!(X, PS)
      println("P (from full matrix): ", PM[1:3,1:3])
      @assert diag(PM) ≈ Pa
      runslow && println("P Slow: ", diag(PS)[1:10])
      runslow && @assert diag(PS) ≈ Pa
      @info "projection tests passed"
    end
  end
end

function rapidreg(::Type{M}=Matrix{Float64}, ::Type{V}=Vector{Float64};
    iter::Int = 100, N::Int = 1_000, K::Int = 2, testerrors::Bool = true,
    qrtype::Type = M, testprimarywithin=false) where {M<:AbstractMatrix, V<:AbstractVector}

  LMtest(M, V, N=N, testerrors=false, testprimarywithin=testprimarywithin, K=K, qrtype=qrtype, iter=iter)
end

function testlagwithin2(N=100_000)
  @info "testing lagwithin2. Failure will result in an error."
  #make the test data
  df::DataFrame = DataFrame(
    val1 = Vector{Union{Float64, Missing}}(undef, N),
    val2 = Vector{Union{Float64, Missing}}(undef, N),
    group = rand(collect(1:1000),N),
    date = rand(collect(Date(1985,11,11):Day(1):Date(2011,11,11)), N))

  for i ∈ 1:N, s ∈ [:val1, :val2]
    if rand() < 0.99
      df[i, s] = rand()
    else
      df[i, s] = missing
    end
  end

  maxnotstale = Day(100)

  #execute! (will also sort)
  try
    Finometrics.lagwithin2!(df, [:val1, :val2],  :group, date=:date) #minimalist version, unsorted
    @assert false
  catch err
    typeof(err) <: AssertionError && error("lagwithin2 should have failed due to lack of sorting")
    sort!(df, [:group, :date])
  end
  dfnostale = deepcopy(df)

  Finometrics.lagwithin2!(dfnostale, [:date, :val1, :val2],  :group, date=:date) #minimalist version, sorted
  Finometrics.leadwithin2!(dfnostale, [:date, :val1, :val2],  :group, date=:date) #minimalist version, sorted
  Finometrics.lagwithin2!(df, [:date, :val1, :val2],
    :group, date=:date, maxnotstale = maxnotstale)
  Finometrics.leadwithin2!(df, [:date, :val1, :val2],
    :group, date=:date, maxnotstale = maxnotstale)

  @assert sum(ismissing.(dfnostale.Ldate)) < sum(ismissing.(df.Ldate))
  @assert sum(ismissing.(dfnostale.Lval1)) < sum(ismissing.(df.Lval1))
  @assert sum(ismissing.(dfnostale.Lval2)) < sum(ismissing.(df.Lval2))
  @assert sum(ismissing.(dfnostale.Ndate)) < sum(ismissing.(df.Ndate))
  @assert sum(ismissing.(dfnostale.Nval1)) < sum(ismissing.(df.Nval1))
  @assert sum(ismissing.(dfnostale.Nval2)) < sum(ismissing.(df.Nval2))

  #Finometrics.leadwithin2!(df, [:val1, :val2],  :group, date=:date) #minimalist version, sorted
  #Finometrics.lagwithin2!(df, [:val1, :val2],  :group, date=:date) #minimalist version, sorted

  #test the no dataframe version
  df.vecLval1 = Finometrics.lagwithin2sorted(df.val1,df.group)
  @assert all(dfnostale.Lval1 .=== df.vecLval1)

  Finometrics.differencewithin2!(df, [:val1, :val2],
    :group, date=:date, maxnotstale = maxnotstale)

  Finometrics.leadwithin2!(df, [:date, :val1, :val2],
    :group, date=:date, maxnotstale = maxnotstale)

  Finometrics.lagwithin2!(df, [:Ndate, :Nval1, :Nval2],
    :group, date=:date, maxnotstale = maxnotstale)

  Finometrics.leadwithin2!(df, [:Ldate, :Lval1, :Lval2],
    :group, date=:date, maxnotstale = maxnotstale)
  @assert (sum(df.LNval1 .=== df.val1) > 0) && (sum(df.LNval2 .=== df.val2) > 0)

  df.TLdate = similar(df.Ldate)
  df.TLval1 = similar(df.Lval1)
  df.TLval2 = similar(df.Lval2)
  #make the test lags
  for sdf ∈ groupby(df, :group)
    for j ∈ 2:size(sdf,1)
      if sdf[j-1,:date] ≥ sdf[j,:date] - maxnotstale
        sdf[j,:TLdate] = sdf[j-1,:date]
        sdf[j,:TLval1] = sdf[j-1,:val1]
        sdf[j,:TLval2] = sdf[j-1,:val2]
      end
    end
  end

  #compute the period
  df.idx = 1:N |> collect

  df.daysfromlag = ((d,Ld)->((d===missing) | (Ld === missing) ? missing : d-Ld)
    ).(df.date, [missing; df.date[1:(end-1)]])
  df.Lgroup = [missing; df.group[1:(end-1)]]
  df.daysfromlag[df.Lgroup .!== df.group] .= missing

  df.daystolead = ((d,Nd)->((d===missing) | (Nd === missing) ? missing : Nd-d)
    ).(df.date, [df.date[2:end]; missing])
  df.Ngroup = [df.group[2:end]; missing]
  df.daystolead[df.Ngroup .!== df.group] .= missing

  @assert all(df.Ldate .=== df.TLdate )

  @assert all(df.Lval1 .=== df.TLval1 )
  @assert all((df.val1 .- df.TLval1) .=== df.Dval1)

  @assert all(df.Lval2 .=== df.TLval2 )
  @assert all((df.val2 .- df.TLval2) .=== df.Dval2)

  df.TNdate = similar(df.Ndate)
  df.TNval1 = similar(df.Nval1)
  df.TNval2 = similar(df.Nval2)
  #make the test lags
  for sdf ∈ groupby(df, :group)
    for j ∈ 1:(size(sdf,1)-1)
      if sdf[j,:date] ≥ sdf[j+1,:date] - maxnotstale
        sdf[j,:TNdate] = sdf[j+1,:date]
        sdf[j,:TNval1] = sdf[j+1,:val1]
        sdf[j,:TNval2] = sdf[j+1,:val2]
      end
    end
  end

  @assert all(df.Ndate .=== df.TNdate )
  @assert all(df.Nval1 .=== df.TNval1 )
  @assert all(df.Nval2 .=== df.TNval2 )

  ####NOTE- commentary for testing if leading a lag is equivent to the original
  #this basically says that leading and then lagging the value produces the original value
  #that is, either val = LNval or a missing value is resulting from one of two places:
  #1) the original val is missing 2) its an endpoint, so the Lval1 is missing
  #(we don't need to worry about the Nval missing since the NL value at t draws from the
  #N value at t-1 which draws from the t value- but this notably implies NLVal1=Val1=missing so
  #we don't need an extra case)
  # the NLval=val is handled analagously, where the original value is missing or its
  #an end point so the Nval1 is missing. We don't need to worry about the Lval missing since the NL
  #value draws from the N value of L which draws from the val, which would imply LNVal1=Val1=missing

  #println(df[1:200,[:idx, :date, :group, :val1, :Lval1, :Nval1, :LNval1, :daysfromlag, :daystolead]])
  @assert all(((df.LNdate .=== missing) .& (df.Ldate .=== missing))
   .| (df.LNdate .=== df.date))
  @assert all(((df.LNval1 .=== missing) .& (df.Lval1 .=== missing))
   .| (df.LNval1 .=== df.val1))
   @assert all(((df.LNval2 .=== missing) .& (df.Lval2 .=== missing))
    .| (df.LNval2 .=== df.val2))

  @assert all(((df.NLdate .=== missing) .& (df.Ndate .=== missing))
   .| (df.NLdate .=== df.date))
  @assert all(((df.NLval1 .=== missing) .& (df.Nval1 .=== missing))
   .| (df.NLval1 .=== df.val1))
   @assert all(((df.NLval2 .=== missing) .& (df.Nval2 .=== missing))
    .| (df.NLval2 .=== df.val2))

end

function testwinsorizequantile(i=100_000; tol = 10^-8)
  v::Vector{MFloat64} = rand(i)
  v = (f->rand()<0.05 ? missing : f).(v)

  @inline completev(v) = view(v, (!ismissing).(v))

  println("test: winsorizequantile(v, .8, twotailed=false)")
  wv = completev(Finometrics.winsorizequantile(v, .8, twosided=false))
  println("results (exp=~0.0,0.8): min: $(minimum(wv)), max: $(maximum(wv))")

  println("test: winsorizequantile(v, .3, twotailed=false)")
  wv = completev(Finometrics.winsorizequantile(v, .3, twosided=false))
  println("results (exp=~0.3,1.0): min: $(minimum(wv)), max: $(maximum(wv))")

  println("test: winsorizequantile(v, .2, twotailed=true)")
  wv = completev(Finometrics.winsorizequantile(v, .2, twosided=true))
  println("results (exp=~0.2,0.8) min: $(minimum(wv)), max: $(maximum(wv))")

  println("autotest: winsorizequantile(v, .8, twotailed=true)")
  wv2 = completev(Finometrics.winsorizequantile(v, .2, twosided=true))
  (sum((abs).(wv2 .- wv) .> tol) > 0) && error("symmetric two-tailed winsorization test failed")

  return nothing
end

function runbasictests()
  @info "Some basic tests. Incomplete, but better than nothing until I get around to making something better"

  testMM(100, N=1000, G=10)
  @time LMtest(Matrix{Float64}, Vector{Float64},
    N=2_000, testerrors=true, K=5, testprimarywithin=true, runslow=true)#, qrtype=CuMatrix{Float32})

  testYearQuarter()
  testYearMonth()
  testlaganddifference()
  testlagwithin2()
  testwinsorizequantile()
end

#runbasictests()

max_stars_repo_name: clintonTE/Finometrics

max_issues_repo_name: clintonTE/Finometrics

max_forks_repo_name: clintonTE/Finometrics