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

using Markdown
using InteractiveUtils

# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error).
macro bind(def, element)
    quote
        local el = $(esc(element))
        global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : missing
        el
    end
end

# ╔═╡ f3c0c18c-3ea9-11eb-1dec-9d913945500c
begin
	using CSV
	using DataFrames
	using Dates
	using Plots
	using PlutoUI
	using Shapefile
	using ZipFile
end

# ╔═╡ ce5e8eb0-3ea9-11eb-0f5e-d9494524efeb
md"# COVID-19 Cases per Municipality"

# ╔═╡ 0f099d5c-3ee5-11eb-22eb-716fd845a490
@bind cmap Radio(["Heat", "Viridis", "Magma", "Sunset", "CoolWarm", "Reds"], default="Heat")

# ╔═╡ c01bc45a-3ee3-11eb-0545-c5656dbc9bd9
md"----"

# ╔═╡ a0982244-3ee4-11eb-2d26-5d2936f1b847
md"### Settings"

# ╔═╡ a9e5b7a8-3ee4-11eb-2dae-95ebaee361e5
size = (500, 600)

# ╔═╡ 3e077378-3ee4-11eb-0330-6d8b95bae896
md"### Load Packages"

# ╔═╡ 5176b978-3ee4-11eb-3a86-157646bd4d22
md"### Get Data"

# ╔═╡ e8c1fff0-3eaa-11eb-1646-510ab72b9fdb
# Create directorties
for dir in ["data", "downloads", "shapefiles", "output"]
    path = joinpath(pwd(), dir)
    if ~ispath(path)
        mkpath(path)
    end
end

# ╔═╡ 473a932e-3eaa-11eb-3403-e3bc710fc555
# Download COVID-19 data
begin
	data_url = "https://data.rivm.nl/covid-19/COVID-19_aantallen_gemeente_per_dag.csv"
    data_path = joinpath(pwd(), "data", split(data_url, "/")[end])
    download(data_url, joinpath(pwd(), "data", data_path))
end

# ╔═╡ 240879da-3eae-11eb-1b50-7708d9135ce0
# Read COVID-19 data
begin
	covid = CSV.File(data_path, pool=false) |> DataFrame

	# Date the figures were update
	date_of_report = maximum(Date.(covid.Date_of_report, DateFormat("Y-m-d H:M:S")))

	# Earliest date for which data is available
	date_of_publ_min = minimum(covid.Date_of_publication)

	# Latest date for which data is available
	date_of_publ_max = maximum(covid.Date_of_publication)

	# Select columns of interest
	select!(covid, ["Date_of_publication", "Municipality_name", "Total_reported"])

	# Drop NA's
	covid = covid[completecases(covid), :]

	# Sum multiple data points for a municipality on a specific date
	covid = combine(
		groupby(covid, [:Date_of_publication, :Municipality_name]),
		:Total_reported .=> sum .=> :Total_reported
	)
end;

# ╔═╡ 64e19a92-3eca-11eb-3b82-e14ba130e6b1
@bind datetime DateField(default=date_of_publ_max)

# ╔═╡ 471ec664-3eaa-11eb-1fe0-a38e52f1999d
# Download shapefiles
begin
	shape_url = "https://www.cbs.nl/-/media/cbs/dossiers/nederland-regionaal/wijk-en-buurtstatistieken/wijkbuurtkaart_2020_v1.zip"
	name_zipfile = split(shape_url, "/")[end]
	path_zipfile = joinpath(pwd(), "downloads", name_zipfile)
	if ~isfile(path_zipfile)
		download(shape_url, path_zipfile)
	end
end

# ╔═╡ f385200a-3ea9-11eb-3e16-036ffd62ea07
# Extract shapefiles
begin
	name_shapefile = "gemeente_2020_v1.shp"
	path_shapefile = joinpath(pwd(), "shapefiles", name_shapefile)
	if ~isfile(path_shapefile)
		r = ZipFile.Reader(path_zipfile)
		for file in r.files
			if split(file.name, ".")[1] == split(name_shapefile, ".")[1]
				open(joinpath(pwd(), "shapefiles", file.name), "w") do io
					write(io, read(file))
				end
			end
		end
	end
end

# ╔═╡ 47377d50-3eb5-11eb-130a-63f690bf28c5
# Shapefile to dataframe
begin
	# Read shapefile
	table = Shapefile.Table(path_shapefile)

	# Create dataframe
	shp = table |> DataFrame
	shp.Shape = Shapefile.shapes(table)

	# Filter for land (i.e. not water)
	row_filter = shp.H2O .== "NEE"

	# Apply filter & select columns
	shp = shp[row_filter, ["GM_NAAM", "AANT_INW", "Shape"]]
end;

# ╔═╡ 2fb4f32c-3ee4-11eb-0eb0-b989926e82f7
md"### Functions"

# ╔═╡ 2c3723ba-3ed4-11eb-00f8-2b6e8ef1927a
function normalize(vec)
    """
    Normalize a Vector to values between 0 and 1
    """

    return[(x - minimum(vec))/(maximum(vec) - minimum(vec)) for x in vec]
end

# ╔═╡ 161d52e6-3ed1-11eb-1bd0-8bcd7d946dba
function color(vec, colormap)
	colors = Array([cgrad(colormap)[value] for value in normalize(vec)])
	return colors
end

# ╔═╡ 25da64be-3ecf-11eb-18b6-59759b67ef34
function chorophlet(datetime, colormap)
	# Filter on selected date
	covid_date = covid[covid.Date_of_publication .== Dates.Date(datetime), :]

	# Join with municipality shapes and data
	df = leftjoin(shp, covid_date, on="GM_NAAM"=>"Municipality_name")

	# Add column (total reported per 100,000 inhabitants)
	df.Per_100_000 = df.Total_reported .* (100_000 ./ df.AANT_INW)

	p = plot(size=size, axis=false, ticks=false)
	for i = 1:nrow(df)
		plot!(df[i, :Shape], color=color(df.Per_100_000, colormap)[i])
	end

	savefig(joinpath(pwd(), "output", "thematic_map.png"))

	return p
end

# ╔═╡ 3abff2be-3ee2-11eb-27ee-b92cdde85622
function chorophlet_no_data()
	title = "Select a date between $date_of_publ_min and $date_of_publ_max"
	return plot(shp.Shape, color="white", size=size,
		axis=false, ticks=false, title=title
	)
end

# ╔═╡ 1f55b380-3ee8-11eb-05a7-979744a438cf
colors = Dict(
	"Heat" => :heat,
	"Viridis" => :viridis,
	"Inferno" => :inferno,
	"Magma" => :magma,
	"Sunset" => :sunset,
	"CoolWarm" => :coolwarm,
	"Pearl" => :pearl,
	"Neon" => :neon,
	"Coffee" => :coffee,
	"Spectral" => :Spectral,
	"RedBlue" => :RdBu,
	"Reds" => :Reds,
	"Blues" => :Blues,
	"Greens" => :Greens,
	"Purples" => :Purples,
	"Oranges" => :Oranges,
	"Leonardo" => :leonardo,
	"Vermeer" => :vermeer,
	"Picasso" => :picasso,
)

# ╔═╡ ed9aa2ee-3ee2-11eb-10c7-3ff216a356e5
if Date(datetime) >= date_of_publ_min && Date(datetime) <= date_of_publ_max
	chorophlet(datetime, colors[cmap])
else
	chorophlet_no_data()
end

# ╔═╡ 31e869c2-3ed4-11eb-2bdc-17937815c701
color(1:15, colors[cmap])

# ╔═╡ 096112fc-3f0a-11eb-2bd4-ab7d2281b348
md"---"

# ╔═╡ 7836bfc8-3f0b-11eb-16cb-6794dbf0313f
md"### Preview Colors"

# ╔═╡ 286a117e-3f07-11eb-0adc-ff6b3cfd2b08
@bind test_color Select([Pair(k, k) for k in keys(colors)], default="Heat")

# ╔═╡ ae04880c-3f0a-11eb-14e1-d3e8bce1f77e
@bind samples Slider(2:20, default=10)

# ╔═╡ 42dfb7ea-3f08-11eb-0f3d-6514c39fca98
color(1:samples, colors[test_color])

# ╔═╡ Cell order:
# ╟─ce5e8eb0-3ea9-11eb-0f5e-d9494524efeb
# ╟─64e19a92-3eca-11eb-3b82-e14ba130e6b1
# ╟─0f099d5c-3ee5-11eb-22eb-716fd845a490
# ╟─ed9aa2ee-3ee2-11eb-10c7-3ff216a356e5
# ╟─31e869c2-3ed4-11eb-2bdc-17937815c701
# ╟─c01bc45a-3ee3-11eb-0545-c5656dbc9bd9
# ╟─a0982244-3ee4-11eb-2d26-5d2936f1b847
# ╠═a9e5b7a8-3ee4-11eb-2dae-95ebaee361e5
# ╟─3e077378-3ee4-11eb-0330-6d8b95bae896
# ╠═f3c0c18c-3ea9-11eb-1dec-9d913945500c
# ╟─5176b978-3ee4-11eb-3a86-157646bd4d22
# ╠═e8c1fff0-3eaa-11eb-1646-510ab72b9fdb
# ╠═473a932e-3eaa-11eb-3403-e3bc710fc555
# ╠═240879da-3eae-11eb-1b50-7708d9135ce0
# ╠═471ec664-3eaa-11eb-1fe0-a38e52f1999d
# ╠═f385200a-3ea9-11eb-3e16-036ffd62ea07
# ╠═47377d50-3eb5-11eb-130a-63f690bf28c5
# ╟─2fb4f32c-3ee4-11eb-0eb0-b989926e82f7
# ╠═2c3723ba-3ed4-11eb-00f8-2b6e8ef1927a
# ╠═161d52e6-3ed1-11eb-1bd0-8bcd7d946dba
# ╠═25da64be-3ecf-11eb-18b6-59759b67ef34
# ╠═3abff2be-3ee2-11eb-27ee-b92cdde85622
# ╠═1f55b380-3ee8-11eb-05a7-979744a438cf
# ╟─096112fc-3f0a-11eb-2bd4-ab7d2281b348
# ╟─7836bfc8-3f0b-11eb-16cb-6794dbf0313f
# ╟─286a117e-3f07-11eb-0adc-ff6b3cfd2b08
# ╟─ae04880c-3f0a-11eb-14e1-d3e8bce1f77e
# ╟─42dfb7ea-3f08-11eb-0f3d-6514c39fca98

max_stars_repo_name: Brinkhuis/Corona

max_issues_repo_name: Brinkhuis/Corona

max_forks_repo_name: Brinkhuis/Corona


text:
using LazySets, LazySets.Approximations, Test, LinearAlgebra, SparseArrays,
      StaticArrays

# fix random number generator seed
using Random
Random.seed!(1234)

# ========================
# Optional dependencies
# ========================
import Distributions, ExponentialUtilities, Expokit, IntervalArithmetic,
       IntervalMatrices, Optim, Pkg, TaylorModels
const IA = IntervalArithmetic
using IntervalArithmetic: IntervalBox
using IntervalMatrices: ±, IntervalMatrix
using TaylorModels: set_variables, TaylorModelN
# ICP currently leads to unsatisfiable package requirements
# using IntervalConstraintProgramming
using Symbolics

# ==============================
# Non-exported helper functions
# ==============================
using LazySets: _leq, _geq, isapproxzero, _isapprox, _ztol, ispermutation
using LazySets.Arrays: isinvertible, inner, allequal,
                       is_cyclic_permutation, SingleEntryVector

global test_suite_basic = true
global test_suite_doctests = VERSION >= v"1.6"
global test_suite_polyhedra = true
global test_suite_plotting = true

if (length(ARGS) == 0) || (ARGS[1] == "--default")
    # default test suite including doctests
elseif ARGS[1] == "--basic"
    # basic test suite
    test_suite_doctests = false
    test_suite_polyhedra = false
    test_suite_plotting = false
elseif ARGS[1] == "--polyhedra"
    # Polyhedra.jl test suite
    test_suite_doctests = false
    test_suite_polyhedra = true
    test_suite_plotting = false
elseif ARGS[1] == "--plot"
    # plotting test suite
    test_suite_doctests = false
    test_suite_polyhedra = false
    test_suite_plotting = true
elseif ARGS[1] == "--all"
    # complete test suite
    test_suite_doctests = true
    test_suite_polyhedra = true
    test_suite_plotting = true
else
    error("unknown parameter 1: $(ARGS[1])")
end

if test_suite_polyhedra || test_suite_plotting
    import Polyhedra
    using CDDLib # for tests that require CDDLib specific backend=...

    # fix namespace conflicts with Polyhedra
    using LazySets: dim, HalfSpace, Interval, Line2D, translate
end

if test_suite_basic

    # =========================
    # Testing utility functions
    # =========================
    @time @testset "LazySets.Util" begin include("Utils/util.jl") end
    @time @testset "LazySets.Comparisons" begin include("Utils/comparisons.jl") end
    @time @testset "LazySets.Interior" begin include("Utils/interior.jl") end

    # ======================================================
    # Testing auxiliary machinery for vectors and matrices
    # ======================================================
    @time @testset "LazySets.Arrays" begin include("Arrays/array_operations.jl") end

    # =======================================
    # Testing interfaces to external packages
    # =======================================
    @time @testset "LazySets.CDDLib" begin include("Interfaces/CDDLib.jl") end

    # =======================================
    # Testing types that inherit from LazySet
    # =======================================
    @time @testset "LazySets.LazySet" begin include("Interfaces/LazySet.jl") end
    @time @testset "LazySets.Singleton" begin include("Sets/Singleton.jl") end
    @time @testset "LazySets.Ball1" begin include("Sets/Ball1.jl") end
    @time @testset "LazySets.Ball2" begin include("Sets/Ball2.jl") end
    @time @testset "LazySets.Ballp" begin include("Sets/Ballp.jl") end
    @time @testset "LazySets.BallInf" begin include("Sets/BallInf.jl") end
    @time @testset "LazySets.Hyperrectangle" begin include("Sets/Hyperrectangle.jl") end
    @time @testset "LazySets.Polygon" begin include("Sets/Polygon.jl") end
    @time @testset "LazySets.Polytope" begin include("Sets/Polytope.jl") end
    @time @testset "LazySets.Polyhedron" begin include("Sets/Polyhedron.jl") end
    @time @testset "LazySets.Zonotope" begin include("Sets/Zonotope.jl") end
    @time @testset "LazySets.ZeroSet" begin include("Sets/ZeroSet.jl") end
    @time @testset "LazySets.EmptySet" begin include("Sets/EmptySet.jl") end
    @time @testset "LazySets.Ellipsoid" begin include("Sets/Ellipsoid.jl") end
    @time @testset "LazySets.Hyperplane" begin include("Sets/Hyperplane.jl") end
    @time @testset "LazySets.HalfSpace" begin include("Sets/HalfSpace.jl") end
    @time @testset "LazySets.Interval" begin include("Sets/Interval.jl") end
    @time @testset "LazySets.LineSegment" begin include("Sets/LineSegment.jl") end
    @time @testset "LazySets.Line2D" begin include("Sets/Line2D.jl") end
    @time @testset "LazySets.Line" begin include("Sets/Line.jl") end
    @time @testset "LazySets.Universe" begin include("Sets/Universe.jl") end
    @time @testset "LazySets.HParallelotope" begin include("Sets/HParallelotope.jl") end
    @time @testset "LazySets.RotatedHyperrectangle" begin include("Sets/RotatedHyperrectangle.jl") end
    @time @testset "LazySets.Star" begin include("Sets/Star.jl") end

    # =========================================
    # Testing types representing set operations
    # =========================================
    @time @testset "LazySets.Bloating" begin include("LazyOperations/Bloating.jl") end
    @time @testset "LazySets.Intersection" begin include("LazyOperations/Intersection.jl") end
    @time @testset "LazySets.ConvexHull" begin include("LazyOperations/ConvexHull.jl") end
    @time @testset "LazySets.ExponentialMap" begin include("LazyOperations/ExponentialMap.jl") end
    @time @testset "LazySets.LinearMap" begin include("LazyOperations/LinearMap.jl") end
    @time @testset "LazySets.InverseLinearMap" begin include("LazyOperations/InverseLinearMap.jl") end
    @time @testset "LazySets.MinkowskiSum" begin include("LazyOperations/MinkowskiSum.jl") end
    @time @testset "LazySets.CartesianProduct" begin include("LazyOperations/CartesianProduct.jl") end
    @time @testset "LazySets.ResetMap" begin include("LazyOperations/ResetMap.jl") end
    @time @testset "LazySets.SymmetricIntervalHull" begin include("LazyOperations/SymmetricIntervalHull.jl") end
    @time @testset "LazySets.Translation" begin include("LazyOperations/Translation.jl") end
    @time @testset "LazySets.AffineMap" begin include("LazyOperations/AffineMap.jl") end

    # ======================
    # Testing set interfaces
    # ======================
    @time @testset "LazySets.CompactSet" begin include("Interfaces/CompactSet.jl") end

    # =========================================================
    # Testing other set types that do not inherit from LazySet
    # =========================================================
    @time @testset "LazySets.Complement" begin include("LazyOperations/Complement.jl") end
    @time @testset "LazySets.PolynomialZonotope" begin include("Sets/PolynomialZonotope.jl") end
    @time @testset "LazySets.Rectification" begin include("LazyOperations/Rectification.jl") end
    @time @testset "LazySets.UnionSet" begin include("LazyOperations/UnionSet.jl") end

    # ===================
    # Concrete operations
    # ===================
    @time @testset "LazySets.area" begin include("ConcreteOperations/area.jl") end
    @time @testset "LazySets.concrete_convex_hull" begin include("ConcreteOperations/convex_hull.jl") end
    @time @testset "LazySets.concrete_cartesian_product" begin include("ConcreteOperations/cartesian_product.jl") end
    @time @testset "LazySets.issubset" begin include("ConcreteOperations/issubset.jl") end
    @time @testset "LazySets.isdisjoint" begin include("ConcreteOperations/isdisjoint.jl") end
    @time @testset "LazySets.distance" begin include("ConcreteOperations/distance.jl") end
    @time @testset "LazySets.isstrictsubset" begin include("ConcreteOperations/isstrictsubset.jl") end
    @time @testset "LazySets.samples" begin include("ConcreteOperations/samples.jl") end

    # =================================================================
    # Algorithms for approximation of convex sets using support vectors
    # =================================================================
    @time @testset "LazySets.Approximations.overapproximation" begin include("Approximations/overapproximate.jl") end
    @time @testset "LazySets.Approximations.underapproximation" begin include("Approximations/underapproximate.jl") end
    @time @testset "LazySets.Approximations.template_directions" begin include("Approximations/template_directions.jl") end
    @time @testset "LazySets.Approximations.box_approximation" begin include("Approximations/box_approximation.jl") end
    @time @testset "LazySets.Approximations.ballinf_approximation" begin include("Approximations/ballinf_approximation.jl") end
    @time @testset "LazySets.Approximations.symmetric_interval_hull" begin include("Approximations/symmetric_interval_hull.jl") end
    @time @testset "LazySets.Approximations.radiusdiameter" begin include("Approximations/radiusdiameter.jl") end
    @time @testset "LazySets.Approximations.decompose" begin include("Approximations/decompose.jl") end
    @time @testset "LazySets.Approximations.hausdorff_distance" begin include("Approximations/hausdorff_distance.jl") end

    # ========================
    # Testing method ambiguity
    # ========================
    @time @testset "LazySets.method_ambiguities" begin
        for package in [LazySets, Approximations, Arrays, Assertions, LazySets.Parallel]
            ambiguities = detect_ambiguities(package)
            @test isempty(ambiguities)
        end
    end

    # ====================================
    # Testing common API of all interfaces
    # (must be the last test because it
    #  loads Polyhedra.jl)
    # ====================================
    include("Utils/check_method_implementation.jl")
    @time @testset "LazySets.interfaces" begin include("Interfaces/interfaces.jl") end
end

if test_suite_plotting
    # define `plot` function as `RecipesBase.apply_recipe`
    import RecipesBase
    struct DummyBackend <: RecipesBase.AbstractBackend end
    struct DummyPlot <: RecipesBase.AbstractPlot{DummyBackend} end
    Base.length(::DummyPlot) = 0
    dict = Dict{Symbol, Any}(:plot_object => DummyPlot())
    plot(args...; kwargs...) = RecipesBase.apply_recipe(dict, args...; kwargs...)

    @time @testset "LazySets.plotting" begin include("Utils/plot.jl") end
end

if test_suite_doctests
    using Documenter
    include("../docs/init.jl")
    @time @testset "LazySets.doctests" begin doctest(LazySets) end
end

ext: jl


text:
@testset "Parallel.Stress" begin
    gint = loadgraph(joinpath(testdir, "testdata", "graph-50-500.jgz"), "graph-50-500")
    c = vec(readdlm(joinpath(testdir, "testdata", "graph-50-500-sc.txt"), ','))
    for g in testdigraphs(gint)
        z  = LightGraphs.stress_centrality(g)
        zp = @inferred(Parallel.stress_centrality(g))
        @test z == zp == c

        xp = Parallel.stress_centrality(g, 3)
        xp2 = Parallel.stress_centrality(g, collect(1:20))
        @test length(xp) == 50
        @test length(xp2) == 50
    end

    g1 = CycleGraph(4)
    add_vertex!(g1)
    add_edge!(g1, 4, 5)

    for g in testgraphs(g1)
        zp = Parallel.stress_centrality(g)
        @test zp == [4, 2, 4, 10, 0]
    end
end


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

"""
    create_application(environment_identifier, name, proxy_type, vpc_id)
    create_application(environment_identifier, name, proxy_type, vpc_id, params::Dict{String,<:Any})

Creates an Amazon Web Services Migration Hub Refactor Spaces application. The account that
owns the environment also owns the applications created inside the environment, regardless
of the account that creates the application. Refactor Spaces provisions the Amazon API
Gateway and Network Load Balancer for the application proxy inside your account.

# Arguments
- `environment_identifier`: The unique identifier of the environment.
- `name`: The name to use for the application.
- `proxy_type`: The proxy type of the proxy created within the application.
- `vpc_id`: The ID of the virtual private cloud (VPC).

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ApiGatewayProxy"`: A wrapper object holding the API Gateway endpoint type and stage
  name for the proxy.
- `"ClientToken"`: A unique, case-sensitive identifier that you provide to ensure the
  idempotency of the request.
- `"Tags"`: The tags to assign to the application. A tag is a label that you assign to an
  Amazon Web Services resource. Each tag consists of a key-value pair.
"""
function create_application(
    EnvironmentIdentifier,
    Name,
    ProxyType,
    VpcId;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "POST",
        "/environments/$(EnvironmentIdentifier)/applications",
        Dict{String,Any}(
            "Name" => Name,
            "ProxyType" => ProxyType,
            "VpcId" => VpcId,
            "ClientToken" => string(uuid4()),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_application(
    EnvironmentIdentifier,
    Name,
    ProxyType,
    VpcId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "POST",
        "/environments/$(EnvironmentIdentifier)/applications",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "Name" => Name,
                    "ProxyType" => ProxyType,
                    "VpcId" => VpcId,
                    "ClientToken" => string(uuid4()),
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_environment(name, network_fabric_type)
    create_environment(name, network_fabric_type, params::Dict{String,<:Any})

Creates an Amazon Web Services Migration Hub Refactor Spaces environment. The caller owns
the environment resource, and they are referred to as the environment owner. The
environment owner has cross-account visibility and control of Refactor Spaces resources
that are added to the environment by other accounts that the environment is shared with.
When creating an environment, Refactor Spaces provisions a transit gateway in your account.

# Arguments
- `name`: The name of the environment.
- `network_fabric_type`: The network fabric type of the environment.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ClientToken"`: A unique, case-sensitive identifier that you provide to ensure the
  idempotency of the request.
- `"Description"`: The description of the environment.
- `"Tags"`: The tags to assign to the environment. A tag is a label that you assign to an
  Amazon Web Services resource. Each tag consists of a key-value pair.
"""
function create_environment(
    Name, NetworkFabricType; aws_config::AbstractAWSConfig=global_aws_config()
)
    return migration_hub_refactor_spaces(
        "POST",
        "/environments",
        Dict{String,Any}(
            "Name" => Name,
            "NetworkFabricType" => NetworkFabricType,
            "ClientToken" => string(uuid4()),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_environment(
    Name,
    NetworkFabricType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "POST",
        "/environments",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "Name" => Name,
                    "NetworkFabricType" => NetworkFabricType,
                    "ClientToken" => string(uuid4()),
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_route(application_identifier, environment_identifier, route_type, service_identifier)
    create_route(application_identifier, environment_identifier, route_type, service_identifier, params::Dict{String,<:Any})

Creates an Amazon Web Services Migration Hub Refactor Spaces route. The account owner of
the service resource is always the environment owner, regardless of which account creates
the route. Routes target a service in the application. If an application does not have any
routes, then the first route must be created as a DEFAULT RouteType. When you create a
route, Refactor Spaces configures the Amazon API Gateway to send traffic to the target
service as follows:   If the service has a URL endpoint, and the endpoint resolves to a
private IP address, Refactor Spaces routes traffic using the API Gateway VPC link.    If
the service has a URL endpoint, and the endpoint resolves to a public IP address, Refactor
Spaces routes traffic over the public internet.   If the service has an Lambda function
endpoint, then Refactor Spaces uses the API Gateway Lambda integration.   A health check is
performed on the service when the route is created. If the health check fails, the route
transitions to FAILED, and no traffic is sent to the service. For Lambda functions, the
Lambda function state is checked. If the function is not active, the function configuration
is updated so that Lambda resources are provisioned. If the Lambda state is Failed, then
the route creation fails. For more information, see the GetFunctionConfiguration's State
response parameter in the Lambda Developer Guide. For public URLs, a connection is opened
to the public endpoint. If the URL is not reachable, the health check fails. For private
URLs, a target group is created and the target group health check is run. The
HealthCheckProtocol, HealthCheckPort, and HealthCheckPath are the same protocol, port, and
path specified in the URL or health URL, if used. All other settings use the default
values, as described in Health checks for your target groups. The health check is
considered successful if at least one target within the target group transitions to a
healthy state.

# Arguments
- `application_identifier`: The ID of the application within which the route is being
  created.
- `environment_identifier`: The ID of the environment in which the route is created.
- `route_type`: The route type of the route. DEFAULT indicates that all traffic that does
  not match another route is forwarded to the default route. Applications must have a default
  route before any other routes can be created. URI_PATH indicates a route that is based on a
  URI path.
- `service_identifier`: The ID of the service in which the route is created. Traffic that
  matches this route is forwarded to this service.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ClientToken"`: A unique, case-sensitive identifier that you provide to ensure the
  idempotency of the request.
- `"Tags"`: The tags to assign to the route. A tag is a label that you assign to an Amazon
  Web Services resource. Each tag consists of a key-value pair..
- `"UriPathRoute"`: The configuration for the URI path route type.
"""
function create_route(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    RouteType,
    ServiceIdentifier;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "POST",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/routes",
        Dict{String,Any}(
            "RouteType" => RouteType,
            "ServiceIdentifier" => ServiceIdentifier,
            "ClientToken" => string(uuid4()),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_route(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    RouteType,
    ServiceIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "POST",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/routes",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "RouteType" => RouteType,
                    "ServiceIdentifier" => ServiceIdentifier,
                    "ClientToken" => string(uuid4()),
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_service(application_identifier, endpoint_type, environment_identifier, name)
    create_service(application_identifier, endpoint_type, environment_identifier, name, params::Dict{String,<:Any})

Creates an Amazon Web Services Migration Hub Refactor Spaces service. The account owner of
the service is always the environment owner, regardless of which account in the environment
creates the service. Services have either a URL endpoint in a virtual private cloud (VPC),
or a Lambda function endpoint.  If an Amazon Web Services resourceis launched in a service
VPC, and you want it to be accessible to all of an environment’s services with VPCs and
routes, apply the RefactorSpacesSecurityGroup to the resource. Alternatively, to add more
cross-account constraints, apply your own security group.

# Arguments
- `application_identifier`: The ID of the application which the service is created.
- `endpoint_type`: The type of endpoint to use for the service. The type can be a URL in a
  VPC or an Lambda function.
- `environment_identifier`: The ID of the environment in which the service is created.
- `name`: The name of the service.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ClientToken"`: A unique, case-sensitive identifier that you provide to ensure the
  idempotency of the request.
- `"Description"`: The description of the service.
- `"LambdaEndpoint"`: The configuration for the Lambda endpoint type.
- `"Tags"`: The tags to assign to the service. A tag is a label that you assign to an
  Amazon Web Services resource. Each tag consists of a key-value pair..
- `"UrlEndpoint"`: The configuration for the URL endpoint type.
- `"VpcId"`: The ID of the VPC.
"""
function create_service(
    ApplicationIdentifier,
    EndpointType,
    EnvironmentIdentifier,
    Name;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "POST",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/services",
        Dict{String,Any}(
            "EndpointType" => EndpointType, "Name" => Name, "ClientToken" => string(uuid4())
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_service(
    ApplicationIdentifier,
    EndpointType,
    EnvironmentIdentifier,
    Name,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "POST",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/services",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "EndpointType" => EndpointType,
                    "Name" => Name,
                    "ClientToken" => string(uuid4()),
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_application(application_identifier, environment_identifier)
    delete_application(application_identifier, environment_identifier, params::Dict{String,<:Any})

Deletes an Amazon Web Services Migration Hub Refactor Spaces application. Before you can
delete an application, you must first delete any services or routes within the application.

# Arguments
- `application_identifier`: The ID of the application.
- `environment_identifier`: The ID of the environment.

"""
function delete_application(
    ApplicationIdentifier,
    EnvironmentIdentifier;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_application(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Deletes an Amazon Web Services Migration Hub Refactor Spaces environment. Before you can
delete an environment, you must first delete any applications and services within the
environment.

# Arguments
- `environment_identifier`: The ID of the environment.

"""
function delete_environment(
    EnvironmentIdentifier; aws_config::AbstractAWSConfig=global_aws_config()
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/environments/$(EnvironmentIdentifier)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_environment(
    EnvironmentIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/environments/$(EnvironmentIdentifier)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Deletes the resource policy set for the environment.

# Arguments
- `identifier`: Amazon Resource Name (ARN) of the resource associated with the policy.

"""
function delete_resource_policy(
    Identifier; aws_config::AbstractAWSConfig=global_aws_config()
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/resourcepolicy/$(Identifier)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_resource_policy(
    Identifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/resourcepolicy/$(Identifier)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_route(application_identifier, environment_identifier, route_identifier)
    delete_route(application_identifier, environment_identifier, route_identifier, params::Dict{String,<:Any})

Deletes an Amazon Web Services Migration Hub Refactor Spaces route.

# Arguments
- `application_identifier`: The ID of the application to delete the route from.
- `environment_identifier`: The ID of the environment to delete the route from.
- `route_identifier`: The ID of the route to delete.

"""
function delete_route(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    RouteIdentifier;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/routes/$(RouteIdentifier)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_route(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    RouteIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/routes/$(RouteIdentifier)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_service(application_identifier, environment_identifier, service_identifier)
    delete_service(application_identifier, environment_identifier, service_identifier, params::Dict{String,<:Any})

Deletes an Amazon Web Services Migration Hub Refactor Spaces service.

# Arguments
- `application_identifier`: Deletes a Refactor Spaces service.  The
  RefactorSpacesSecurityGroup security group must be removed from all Amazon Web Services
  resources in the virtual private cloud (VPC) prior to deleting a service with a URL
  endpoint in a VPC.
- `environment_identifier`: The ID of the environment that the service is in.
- `service_identifier`: The ID of the service to delete.

"""
function delete_service(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    ServiceIdentifier;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/services/$(ServiceIdentifier)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_service(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    ServiceIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/services/$(ServiceIdentifier)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_application(application_identifier, environment_identifier)
    get_application(application_identifier, environment_identifier, params::Dict{String,<:Any})

Gets an Amazon Web Services Migration Hub Refactor Spaces application.

# Arguments
- `application_identifier`: The ID of the application.
- `environment_identifier`: The ID of the environment.

"""
function get_application(
    ApplicationIdentifier,
    EnvironmentIdentifier;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_application(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Gets an Amazon Web Services Migration Hub Refactor Spaces environment.

# Arguments
- `environment_identifier`: The ID of the environment.

"""
function get_environment(
    EnvironmentIdentifier; aws_config::AbstractAWSConfig=global_aws_config()
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_environment(
    EnvironmentIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Gets the resource-based permission policy that is set for the given environment.

# Arguments
- `identifier`: The Amazon Resource Name (ARN) of the resource associated with the policy.

"""
function get_resource_policy(Identifier; aws_config::AbstractAWSConfig=global_aws_config())
    return migration_hub_refactor_spaces(
        "GET",
        "/resourcepolicy/$(Identifier)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_resource_policy(
    Identifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/resourcepolicy/$(Identifier)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_route(application_identifier, environment_identifier, route_identifier)
    get_route(application_identifier, environment_identifier, route_identifier, params::Dict{String,<:Any})

Gets an Amazon Web Services Migration Hub Refactor Spaces route.

# Arguments
- `application_identifier`: The ID of the application.
- `environment_identifier`: The ID of the environment.
- `route_identifier`: The ID of the route.

"""
function get_route(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    RouteIdentifier;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/routes/$(RouteIdentifier)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_route(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    RouteIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/routes/$(RouteIdentifier)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_service(application_identifier, environment_identifier, service_identifier)
    get_service(application_identifier, environment_identifier, service_identifier, params::Dict{String,<:Any})

Gets an Amazon Web Services Migration Hub Refactor Spaces service.

# Arguments
- `application_identifier`: The ID of the application.
- `environment_identifier`: The ID of the environment.
- `service_identifier`: The ID of the service.

"""
function get_service(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    ServiceIdentifier;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/services/$(ServiceIdentifier)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_service(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    ServiceIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/services/$(ServiceIdentifier)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Lists all the Amazon Web Services Migration Hub Refactor Spaces applications within an
environment.

# Arguments
- `environment_identifier`: The ID of the environment.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return with a single call. To retrieve
  the remaining results, make another call with the returned nextToken value.
- `"nextToken"`: The token for the next page of results.
"""
function list_applications(
    EnvironmentIdentifier; aws_config::AbstractAWSConfig=global_aws_config()
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_applications(
    EnvironmentIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Lists all the virtual private clouds (VPCs) that are part of an Amazon Web Services
Migration Hub Refactor Spaces environment.

# Arguments
- `environment_identifier`: The ID of the environment.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return with a single call. To retrieve
  the remaining results, make another call with the returned nextToken value.
- `"nextToken"`: The token for the next page of results.
"""
function list_environment_vpcs(
    EnvironmentIdentifier; aws_config::AbstractAWSConfig=global_aws_config()
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/vpcs";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_environment_vpcs(
    EnvironmentIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/vpcs",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Lists Amazon Web Services Migration Hub Refactor Spaces environments owned by a caller
account or shared with the caller account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return with a single call. To retrieve
  the remaining results, make another call with the returned nextToken value.
- `"nextToken"`: The token for the next page of results.
"""
function list_environments(; aws_config::AbstractAWSConfig=global_aws_config())
    return migration_hub_refactor_spaces(
        "GET", "/environments"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_environments(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_routes(application_identifier, environment_identifier)
    list_routes(application_identifier, environment_identifier, params::Dict{String,<:Any})

Lists all the Amazon Web Services Migration Hub Refactor Spaces routes within an
application.

# Arguments
- `application_identifier`: The ID of the application.
- `environment_identifier`: The ID of the environment.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return with a single call. To retrieve
  the remaining results, make another call with the returned nextToken value.
- `"nextToken"`: The token for the next page of results.
"""
function list_routes(
    ApplicationIdentifier,
    EnvironmentIdentifier;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/routes";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_routes(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/routes",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_services(application_identifier, environment_identifier)
    list_services(application_identifier, environment_identifier, params::Dict{String,<:Any})

Lists all the Amazon Web Services Migration Hub Refactor Spaces services within an
application.

# Arguments
- `application_identifier`: The ID of the application.
- `environment_identifier`: The ID of the environment.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return with a single call. To retrieve
  the remaining results, make another call with the returned nextToken value.
- `"nextToken"`: The token for the next page of results.
"""
function list_services(
    ApplicationIdentifier,
    EnvironmentIdentifier;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/services";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_services(
    ApplicationIdentifier,
    EnvironmentIdentifier,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/environments/$(EnvironmentIdentifier)/applications/$(ApplicationIdentifier)/services",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Lists the tags of a resource. The caller account must be the same as the resource’s
OwnerAccountId. Listing tags in other accounts is not supported.

# Arguments
- `resource_arn`: The Amazon Resource Name (ARN) of the resource.

"""
function list_tags_for_resource(
    ResourceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return migration_hub_refactor_spaces(
        "GET",
        "/tags/$(ResourceArn)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_tags_for_resource(
    ResourceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "GET",
        "/tags/$(ResourceArn)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_resource_policy(policy, resource_arn)
    put_resource_policy(policy, resource_arn, params::Dict{String,<:Any})

Attaches a resource-based permission policy to the Amazon Web Services Migration Hub
Refactor Spaces environment. The policy must contain the same actions and condition
statements as the
arn:aws:ram::aws:permission/AWSRAMDefaultPermissionRefactorSpacesEnvironment permission in
Resource Access Manager. The policy must not contain new lines or blank lines.

# Arguments
- `policy`: A JSON-formatted string for an Amazon Web Services resource-based policy.
- `resource_arn`: The Amazon Resource Name (ARN) of the resource to which the policy is
  being attached.

"""
function put_resource_policy(
    Policy, ResourceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return migration_hub_refactor_spaces(
        "PUT",
        "/resourcepolicy",
        Dict{String,Any}("Policy" => Policy, "ResourceArn" => ResourceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_resource_policy(
    Policy,
    ResourceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "PUT",
        "/resourcepolicy",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("Policy" => Policy, "ResourceArn" => ResourceArn),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    tag_resource(resource_arn, tags)
    tag_resource(resource_arn, tags, params::Dict{String,<:Any})

Removes the tags of a given resource. Tags are metadata which can be used to manage a
resource. To tag a resource, the caller account must be the same as the resource’s
OwnerAccountId. Tagging resources in other accounts is not supported.  Amazon Web Services
Migration Hub Refactor Spaces does not propagate tags to orchestrated resources, such as an
environment’s transit gateway.

# Arguments
- `resource_arn`: The Amazon Resource Name (ARN) of the resource
- `tags`: The new or modified tags for the resource.

"""
function tag_resource(ResourceArn, Tags; aws_config::AbstractAWSConfig=global_aws_config())
    return migration_hub_refactor_spaces(
        "POST",
        "/tags/$(ResourceArn)",
        Dict{String,Any}("Tags" => Tags);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function tag_resource(
    ResourceArn,
    Tags,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "POST",
        "/tags/$(ResourceArn)",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("Tags" => Tags), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    untag_resource(resource_arn, tag_keys)
    untag_resource(resource_arn, tag_keys, params::Dict{String,<:Any})

Adds to or modifies the tags of the given resource. Tags are metadata which can be used to
manage a resource. To untag a resource, the caller account must be the same as the
resource’s OwnerAccountId. Untagging resources across accounts is not supported.

# Arguments
- `resource_arn`: The Amazon Resource Name (ARN) of the resource.
- `tag_keys`: The list of keys of the tags to be removed from the resource.

"""
function untag_resource(
    ResourceArn, tagKeys; aws_config::AbstractAWSConfig=global_aws_config()
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/tags/$(ResourceArn)",
        Dict{String,Any}("tagKeys" => tagKeys);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function untag_resource(
    ResourceArn,
    tagKeys,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return migration_hub_refactor_spaces(
        "DELETE",
        "/tags/$(ResourceArn)",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("tagKeys" => tagKeys), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end


text:
# kernel execution

export AbstractGPUBackend, AbstractKernelContext, gpu_call

abstract type AbstractGPUBackend end

abstract type AbstractKernelContext end

"""
    backend(T::Type)
    backend(x)

Gets the GPUArrays back-end responsible for managing arrays of type `T`.
"""
backend(::Type) = error("This object is not a GPU array") # COV_EXCL_LINE
backend(x) = backend(typeof(x))

"""
    gpu_call(kernel::Function, arg0, args...; kwargs...)

Executes `kernel` on the device that backs `arg` (see [`backend`](@ref)), passing along any
arguments `args`. Additionally, the kernel will be passed the kernel execution context (see
[`AbstractKernelContext`]), so its signature should be `(ctx::AbstractKernelContext, arg0,
args...)`.

The keyword arguments `kwargs` are not passed to the function, but are interpreted on the
host to influence how the kernel is executed. The following keyword arguments are supported:

- `target::AbstractArray`: specify which array object to use for determining execution
  properties (defaults to the first argument `arg0`).
- `total_threads::Int`: how many threads should be launched _in total_. The actual number of
  threads and blocks is determined using a heuristic. Defaults to the length of `arg0` if
  no other keyword arguments that influence the launch configuration are specified.
- `threads::Int` and `blocks::Int`: configure exactly how many threads and blocks are
  launched. This cannot be used in combination with the `total_threads` argument.
- `name::String`: inform the back end about the name of the kernel to be executed.
  This can be used to emit better diagnostics, and is useful with anonymous kernels.
"""
function gpu_call(kernel::F, args::Vararg{Any,N};
                  target::AbstractArray=first(args),
                  total_threads::Union{Int,Nothing}=nothing,
                  threads::Union{Int,Nothing}=nothing,
                  blocks::Union{Int,Nothing}=nothing,
                  name::Union{String,Nothing}=nothing) where {F,N}
    # non-trivial default values for launch configuration
    if total_threads===nothing && threads===nothing && blocks===nothing
        total_threads = length(target)
    elseif total_threads===nothing
        if threads === nothing
            threads = 1
        end
        if blocks === nothing
            blocks = 1
        end
    elseif threads!==nothing || blocks!==nothing
        error("Cannot specify both total_threads and threads/blocks configuration")
    end

    if total_threads !== nothing
        @assert total_threads > 0
        heuristic = launch_heuristic(backend(target), kernel, args...)
        config = launch_configuration(backend(target), heuristic, total_threads)
        gpu_call(backend(target), kernel, args, config.threads, config.blocks; name=name)
    else
        @assert threads > 0
        @assert blocks > 0
        gpu_call(backend(target), kernel, args, threads, blocks; name=name)
    end
end

# how many threads and blocks this kernel need to fully saturate the GPU.
# this can be specialised if more sophisticated heuristics are available.
#
# the `maximize_blocksize` indicates whether the kernel benifits from a large block size
function launch_heuristic(backend::AbstractGPUBackend, kernel, args...;
                          maximize_blocksize=false)
    return (threads=256, blocks=32)
end

# determine how many threads and blocks to actually launch given upper limits.
# returns a tuple of blocks, threads, and elements_per_thread (which is always 1
# unless specified that the kernel can handle a number of elements per thread)
function launch_configuration(backend::AbstractGPUBackend, heuristic,
                              elements::Int, elements_per_thread::Int=1)
    threads = clamp(elements, 1, heuristic.threads)
    blocks = max(cld(elements, threads), 1)

    # FIXME: use grid-stride loop when we can't launch the number of blocks we need

    if false && elements_per_thread > 1 && blocks > heuristic.blocks
        # we want to launch more blocks than required, so prefer a grid-stride loop instead
        # NOTE: this does not seem to improve performance
        nelem = clamp(cld(blocks, heuristic.blocks), 1, elements_per_thread)
        blocks = cld(blocks, nelem)
        (threads=threads, blocks=blocks, elements_per_thread=nelem)
    else
        (threads=threads, blocks=blocks, elements_per_thread=1)
    end
end

gpu_call(backend::AbstractGPUBackend, kernel, args, threads::Int, blocks::Int; kwargs...) =
    error("Not implemented") # COV_EXCL_LINE


text:
# # Interfaces

# This file defines abstract super types and includes further method
# definitions for these types so we can write our algorithm without
# the actual implementations being available.
# This also avoids some import order complications.

# ## Abstract Super Types

# ### Surrogate Models
# Each surrogate model type is configured via a data structure
# that implements `SurrogateConfig`.
# Such a configuration struct should be exported by the main module.
"Abstract super type for a configuration type defining some surrogate model."
abstract type SurrogateConfig end

"Abstract super type for meta data that is used to build a model."
abstract type SurrogateMeta end

"Abstract super type for the actual surrogate models."
abstract type SurrogateModel end

"Abstract super type wrapping around an objective, its model and the surrogate meta."
abstract type AbstractSurrogateWrapper end

"Wrapper around a list of `AbstractSurrogateWrapper`s."
abstract type AbstractSurrogateContainer end

# Define a shorthand for the type of what we save in some `AbstractIterSaveable`.
const ContainerSaveable = Union{Nothing,Tuple{Vararg{<:Union{Nothing,SurrogateMeta}}}}

# ### MOPs
# Internally we use implementations of the `AbstractObjective` for
# managing the MOP objectives and evaluation.
"Abstract super type for any kind of (vector) objective."
abstract type AbstractObjective <: MOI.AbstractVectorFunction end

# Our actual problem is repersented by an `AbstractMOP`.
"""
    AbstractMOP{T}

Abstract super type for multi-objective optimization problems.
`T` is `true` if the problem is modifyable and `false elsewise.

The user should define a `MixedMOP<:AbstractMOP{true}`, see [`MixedMOP`](@ref).
"""
abstract type AbstractMOP{T} <: MOI.ModelLike end

# ### Internal Data Managment

# For internal data management we make some effort to keep everything
# structured.
# To save the intermediate results:
"Abstract super type for stuff stored in the database."
abstract type AbstractResult{XT <: VecF, YT <: VecF} end

# `AbstractIterData` is passed to functions and provides access to
# the current site and value vectors and the trust region radius.
"Abstract super type for iteration data. Implemented by `IterData`.
Has type parameters for the vector type of itaration site, value vector and trust region radius."
abstract type AbstractIterData{XT <: VecF, YT <: VecF, DT <: NumOrVecF} end
"Abstract super type for some saveable representation of `AbstractIterData`."
abstract type AbstractIterSaveable{XT <: VecF, YT <: VecF, DT <: NumOrVecF, C <: ContainerSaveable } end

# A shorthand for everything that is either nothing or an `AbstractIterSaveable`:
const NothingOrSaveable = Union{Nothing, AbstractIterSaveable}

# Everything is kept in a database:
"Abstract database super type. Implemented by `ArrayDB` and `MockDB`."
abstract type AbstractDB{R<:AbstractResult, S<:NothingOrSaveable} end

# ### Algorithm configuration.

# We have our own type to define the solution of the trust region sub-problems:
"Abstract super type for descent step configuration."
abstract type AbstractDescentConfig end

# This might be returned by the general algorithm configuration implementing `AbstractConfig`:
"Abstract super type for user configurable algorithm configuration."
abstract type AbstractConfig end

# ### Differentiation
"Super type for making (automatic) differentiation comfortable."
abstract type DiffFn end

# Method definitions for `DiffFn`s:
get_gradient( :: DiffFn, :: Vec, :: Int ) :: Vec = nothing
get_jacobian( :: DiffFn, :: Vec ) :: Mat = nothing
get_hessian( :: DiffFn, :: Vec, :: Int ) :: Mat = nothing

# ### Enums

# These codes should be availabe everywhere and that is why we
# define them here:

@enum ITER_TYPE begin
    ACCEPTABLE = 1;     # accept trial point, shrink radius
    SUCCESSFULL = 2;    # accept trial point, grow radius
    MODELIMPROVING = 3; # reject trial point, keep radius
    INACCEPTABLE = 4;   # reject trial point, shrink radius (much)
end

@enum STOP_CODE begin
    CONTINUE = 1
    MAX_ITER = 2
    BUDGET_EXHAUSTED = 3
    CRITICAL = 4
    TOLERANCE = 5
end

# ### Interface Definitions
# Most of the interfaces are defined in subfiles and we include
# them here:
include("SurrogateModelInterface.jl");
include("AbstractSurrogateContainerInterface.jl")
include("AbstractObjectiveInterface.jl");
include("AbstractMOPInterface.jl");
include("AbstractIterDataInterface.jl")
include("AbstractResultInterface.jl")
include("AbstractDBInterface.jl")
include("AbstractConfigInterface.jl")


text:
"""
`module  JAC.AlphaVariation`
    ... a submodel of JAC that contains all methods for computing alpha-variation parameters for some levels.
"""
module AlphaVariation

    using Printf, JAC, ..Basics, ..Defaults, ..ManyElectron, ..Radial, ..TableStrings
    global JAC_counter = 0

    """
    `struct  AlphaVariation.Settings  <:  AbstractPropertySettings`  ... defines a type for the details and parameters of computing alpha-variation parameters.

        + calcK                    ::Bool             ... True if the enhancement factor need to be calculated, and false otherwise.
        + printBefore              ::Bool             ... True if a list of selected levels is printed before the actual computations start.
        + levelSelection           ::LevelSelection   ... Specifies the selected levels, if any.
    """
    struct Settings  <:  AbstractPropertySettings
        calcK                      ::Bool
        printBefore                ::Bool
        levelSelection             ::LevelSelection
    end

    """
    `AlphaVariation.Settings()`  ... constructor for an `empty` instance of AlphaVariation.Settings for the computation of alpha variation parameters.
    """
    function Settings()
        Settings(false, false, LevelSelection() )
    end

    # `Base.show(io::IO, settings::AlphaVariation.Settings)`  ... prepares a proper printout of the variable settings::AlphaVariation.Settings.
    function Base.show(io::IO, settings::AlphaVariation.Settings)
        println(io, "calcK:                    $(settings.calcK)  ")
        println(io, "printBefore:              $(settings.printBefore)  ")
        println(io, "levelSelection:           $(settings.levelSelection)  ")
    end

    """
    `struct  AlphaVariation.Outcome`
        ... defines a type to keep the outcome of a alpha-variation computation, such as the K enhancement factor as well other results.

        + level                     ::Level              ... Atomic level to which the outcome refers to.
        + K                         ::Float64            ... K enhancement parameter
    """
    struct Outcome
        level                       ::Level
        K                           ::Float64
    end

    """
    `AlphaVariation.Outcome()`  ... constructor for an `empty` instance of AlphaVariation..Outcome for the computation of alpha-variation properties.
    """
    function Outcome()
        Outcome(Level(), 0.)
    end

    # `Base.show(io::IO, outcome::AlphaVariation.Outcome)`  ... prepares a proper printout of the variable outcome::AlphaVariation.Outcome.
    function Base.show(io::IO, outcome::AlphaVariation.Outcome)
        println(io, "level:                   $(outcome.level)  ")
        println(io, "K:                       $(outcome.K)  ")
    end

    """
    `AlphaVariation.computeOutcomes(multiplet::Multiplet, nm::Nuclear.Nuclear.Model, grid::Radial.Grid, settings::AlphaVariation.Settings; output=true)`
        ... to compute (as selected) the alpha-variation parameters for the levels of the given multiplet and as specified by the given settings.
            The results are printed in neat tables to screen but nothing is returned otherwise.
    """
    function computeOutcomes(multiplet::Multiplet, nm::Nuclear.Nuclear.Model, grid::Radial.Grid, settings::AlphaVariation.Settings; output=true)
        println("")
        printstyled("AlphaVariation.computeOutcomes(): The computation of the alpha-variation parameters starts now ... \n", color=:light_green)
        printstyled("-------------------------------------------------------------------------------------------------- \n", color=:light_green)
        #
        outcomes = AlphaVariation.determineOutcomes(multiplet, settings)
        # Display all selected levels before the computations start
        if  settings.printBefore    AlphaVariation.displayOutcomes(outcomes)    end
        # Calculate all amplitudes and requested properties
        newOutcomes = AlphaVariation.Outcome[]
        for  outcome in outcomes
            ## newOutcome = AlphaVariation.computeAmplitudesProperties(outcome, nm, grid, settings)
            newOutcome = AlphaVariation.Outcome(outcome.level, 2.0)
            push!( newOutcomes, newOutcome)
        end
        # Print all results to screen
        AlphaVariation.displayResults(stdout, newOutcomes)
        printSummary, iostream = Defaults.getDefaults("summary flag/stream")
        if  printSummary    AlphaVariation.displayResults(iostream, newOutcomes)   end
        #
        if    output    return( newOutcomes )
        else            return( nothing )
        end
    end

    """
    `AlphaVariation.determineOutcomes(multiplet::Multiplet, settings::AlphaVariation.Settings)`
        ... to determine a list of Outcomes's for the computation of the alpha-variation parameters for the given multiplet.
            It takes into account the particular selections and settings. An Array{AlphaVariation.Outcome,1} is returned.
            Apart from the level specification, all physical properties are set to zero during the initialization process.
    """
    function  determineOutcomes(multiplet::Multiplet, settings::AlphaVariation.Settings)
        outcomes = AlphaVariation.Outcome[]
        for  level  in  multiplet.levels
            if  Basics.selectLevel(level, settings.levelSelection)
                push!( outcomes, AlphaVariation.Outcome(level, 0.) )
            end
        end
        return( outcomes )
    end

    """
    `AlphaVariation.displayOutcomes(outcomes::Array{AlphaVariation.Outcome,1})`  ... to display a list of levels that have been selected
         for the computations. A small neat table of all selected levels and their energies is printed but nothing is returned otherwise.
    """
    function  displayOutcomes(outcomes::Array{AlphaVariation.Outcome,1})
        nx = 43
        println(" ")
        println("  Selected AlphaVariation levels:")
        println(" ")
        println("  ", TableStrings.hLine(nx))
        sa = "  ";   sb = "  "
        sa = sa * TableStrings.center(10, "Level"; na=2);                             sb = sb * TableStrings.hBlank(12)
        sa = sa * TableStrings.center(10, "J^P";   na=4);                             sb = sb * TableStrings.hBlank(14)
        sa = sa * TableStrings.center(14, "Energy"; na=4);
        sb = sb * TableStrings.center(14, TableStrings.inUnits("energy"); na=4)
        println(sa);    println(sb);    println("  ", TableStrings.hLine(nx))
        #
        for  outcome in outcomes
            sa  = "  ";    sym = LevelSymmetry( outcome.level.J, outcome.level.parity)
            sa = sa * TableStrings.center(10, TableStrings.level(outcome.level.index); na=2)
            sa = sa * TableStrings.center(10, string(sym); na=4)
            sa = sa * @sprintf("%.8e", Defaults.convertUnits("energy: from atomic", outcome.level.energy)) * "    "
            println( sa )
        end
        println("  ", TableStrings.hLine(nx))
        #
        return( nothing )
    end

    """
    `AlphaVariation.displayResults(stream::IO, outcomes::Array{AlphaVariation.Outcome,1})`
        ... to display the energies, M_ms and F-parameters, etc. for the selected levels. A neat table is printed but nothing
            is returned otherwise.
    """
    function  displayResults(stream::IO, outcomes::Array{AlphaVariation.Outcome,1})
        nx = 64
        println(stream, " ")
        println(stream, "  Alpha variation parameters:")
        println(stream, " ")
        println(stream, "  ", TableStrings.hLine(nx))
        sa = "  ";   sb = "  "
        sa = sa * TableStrings.center(10, "Level"; na=2);                             sb = sb * TableStrings.hBlank(12)
        sa = sa * TableStrings.center(10, "J^P";   na=4);                             sb = sb * TableStrings.hBlank(14)
        sa = sa * TableStrings.center(14, "Energy"; na=4)
        sb = sb * TableStrings.center(14, TableStrings.inUnits("energy"); na=4)
        sa = sa * TableStrings.center(14, "K";     na=4)
        sb = sb * TableStrings.center(14, "    " ; na=4)
        println(stream, sa);    println(stream, sb);    println(stream, "  ", TableStrings.hLine(nx))
        #
        for  outcome in outcomes
            sa  = "  ";    sym = LevelSymmetry( outcome.level.J, outcome.level.parity)
            sa = sa * TableStrings.center(10, TableStrings.level(outcome.level.index); na=2)
            sa = sa * TableStrings.center(10, string(sym); na=4)
            energy = 1.0
            sa = sa * @sprintf("%.8e", Defaults.convertUnits("energy: from atomic", energy))              * "    "
            sa = sa * @sprintf("%.8e", outcome.K)                                               * "    "
            println(stream, sa )
        end
        println(stream, "  ", TableStrings.hLine(nx), "\n\n")
        #
        return( nothing )
    end

end # module


text:
using CUDA, DataStructures, StaticArrays

CUDA.allowscalar(false)

struct Cell{T}
    value :: T
    depth :: Int32
    output_index :: Int32
end

function Cell(cell :: Cell)
    return cell
end

function is_valid(cell :: Cell)
    return cell.output_index >= 1
end

abstract type AFrame{T, L} end

function Base.getindex(f :: AFrame{T, L}, i) :: Cell{T} where {T, L}
    return f.cells[i]
end

function Base.setindex!(f :: AFrame{T, L}, val :: Cell{T}, i) where {T, L}
    f.cells[i] = val
end

mutable struct Frame{T, L} <: AFrame{T, L}
    cells :: MVector{L, Cell{T}}
    count :: Int32
    age :: Int32
end

function Base.push!(f :: Frame{T, L}, val :: Cell{T}) where {T, L}
    i = length(f)
    f[i + 1] = val
    f.count += 1
end

mutable struct CuFrame{T, L} <: AFrame{T, L}
    cells :: CuArray{Cell{T}}
    count :: Int32
    age :: Int32
end

struct FramePool{T, F}
    pool :: Array{F}
    default_value :: T
end

struct VirtualStack{T, F}
    ready :: PriorityQueue{F, Int32}
    partial :: Array{F}
    flags :: Array{Bool}
    threshold :: Int32
end

struct Program{T, U, F}
    stacks :: Dict{Symbol, VirtualStack{T, F}}
    value_functions :: Dict{Symbol, Union{Function, Tuple{Function, Any}}}
    dest_functions :: Dict{Symbol, Function}
    flow :: Dict{Symbol, Union{Symbol, Tuple{Symbol, Symbol}}}
    pool :: FramePool{T, F}
    dest :: Array{U}
end

function FramePool{T, F}(default_value :: T) where {T, F}
    return FramePool{T, F}(Array{F}(undef, 0), default_value)
end

function fetch!(pool :: FramePool{T, F}) :: F where {T, L, F <: AFrame{T, L}}

    if length(pool.pool) > 0
        #@debug "Reusing array"
        return pop!(pool.pool)
    else
        #@debug "Creating new array"
        arr = MVector{L, Cell{T}}(undef)
        @simd for i in 1:length(arr)
            arr[i] = Cell{T}(pool.default_value, 0, -1)
        end

        out = F(arr, 0, 0)
        return out
    end
end

function realloc_kernel(cells, value :: T, N) where T
    i = threadIdx().x
    for iter in 1:N
        cells[i + (iter - 1) * 1024] = Cell{T}(value, 0, -1)
    end
    return nothing
end

function reallocate!(frame_pool :: FramePool{T, F}, frame :: CuFrame{T, L}) where {T, F, L}
    @cuda threads=1024 realloc_kernel(frame.cells, frame_pool.default_value, Int(L / 1024))
    frame.count = 0
    push!(frame_pool.pool, frame)
end

function reallocate!(frame_pool :: FramePool{T, F}, frame :: Frame{T, L}) where {T, F, L}
    #@debug "Reallocating array"
    @simd for i in 1:L
        frame.cells[i] = Cell{T}(frame_pool.default_value, 0, -1)
    end
    frame.count = 0
    push!(frame_pool.pool, frame)
end

function Base.length(frame :: AFrame)
    return frame.count
end

function Base.size(frame :: AFrame{T, L}) where {T, L}
    return L
end

function Base.size(frame_pool :: FramePool{T, F}) where {T, L, F <: AFrame{T, L}}
    return L
end

function Base.length(frame_pool :: FramePool)
    return length(frame_pool.pool)
end

function ready(stack :: VirtualStack)
    return length(stack.ready) > 0
end

function Base.empty(stack :: VirtualStack)
    return length(stack.ready) == length(stack.partial) == 0
end

function VirtualStack{T, F}(threshold) where {T, F}
    return VirtualStack{T, F}(PriorityQueue{F, Int32}(),
                           Array{F}(undef, 0),
                           Array{Bool}(undef, 0), threshold)
end

function collapse!(stack, frame_pool)
    if length(stack.partial) == 0
        return
    end
    frame = pop!(stack.partial)
    cum_sum = frame.count
    new_age = frame.age
    #@debug "attempting collapse"
    while length(stack.partial) > 0 && cum_sum + stack.partial[end].count <= size(frame_pool)
        temp = pop!(stack.partial)
        new_age = min(new_age, temp.age)
        frame.cells[cum_sum + 1: cum_sum + temp.count] .= temp.cells[1:temp.count]
        cum_sum += temp.count
    #    @debug "collapsed 1x"
        reallocate!(frame_pool, temp)
    end

    frame.count = cum_sum
    enqueue!(stack.ready, frame, new_age)
end

function attempt_collapse!(stack :: VirtualStack, frame_pool)
    if length(stack.partial) > 0 && sum(p.count for p in stack.partial) > stack.threshold
        collapse!(stack, frame_pool)
    end
end

function Base.pop!(stack :: VirtualStack{T, F}) :: F where {T, F}
    return dequeue!(stack.ready)
end

function Base.pop!(stack :: VirtualStack{T, F}, frame_pool :: FramePool{T, F}) :: F where {T, F}
    if ready(stack)
        return pop!(stack)
    end
    collapse!(stack, frame_pool)
    return pop!(stack)
end

function Base.pop!(program :: Program{T, U, F}, stack_name :: Symbol) where {T, U, F}
    pop!(program.stacks[stack_name], program.pool)
end

function Base.push!(program :: Program{T, U, F}, key :: Symbol, frame :: F) where {T, U, F}
    if frame.count == 0
        reallocate!(program.pool, frame)
        return
    end
    if key == :end
        reallocate!(program.pool, frame)
        return
    end

    stack = program.stacks[key]
    if frame.count >= stack.threshold
        enqueue!(stack.ready, frame, frame.age)
    else
        push!(stack.partial, frame)
        attempt_collapse!(stack, program.pool)
    end
end


text:
"""
Functionality for dealing with HTTP cookies.
"""
module Cookies

using HTTP, Nullables
using Genie, Genie.Encryption

"""
    get(res::HTTP.Response, key::Union{String,Symbol}) :: Nullable{String}

Retrieves a value stored on the cookie as `key` from the `Respose` object.
"""
function get(res::HTTP.Response, key::Union{String,Symbol}; encrypted::Bool = true) :: Nullable{String}
  if haskey(Dict(res.headers), "Set-Cookie")
    cookies = todict(res)
    if haskey(cookies, string(key))
      value = cookies[string(key)]
      encrypted && (value = Genie.Encryption.decrypt(value))

      return Nullable{String}(value)
    end
  end

  Nullable{String}()
end

"""
"""
function get!!(res::HTTP.Response, key::Union{String,Symbol}; encrypted::Bool = true) :: String
  get(res, key, encrypted = encrypted) |> Nullables.get
end

"""
    get(req::Request, key::Union{String,Symbol}) :: Nullable{String}

Retrieves a value stored on the cookie as `key` from the `Request` object.
"""
function get(req::HTTP.Request, key::Union{String,Symbol}; encrypted::Bool = true) :: Nullable{String}
  if haskey(Dict(req.headers), "Cookie")
    cookies = to_dict(req)
    if haskey(cookies, string(key))
      value = cookies[string(key)]
      encrypted && (value = Genie.Encryption.decrypt(value))

      return Nullable{String}(value)
    end
  end

  Nullable{String}()
end

"""
"""
function get!!(req::HTTP.Request, key::Union{String,Symbol}; encrypted::Bool = true) :: String
  get(req, key, encrypted = encrypted) |> Nullables.get
end

"""
"""
function getcookies(req::HTTP.Request) :: Vector{HTTP.Cookies.Cookie}
  HTTP.Cookies.cookies(req)
end
function getcookies(req::HTTP.Request, matching::String) :: Vector{HTTP.Cookies.Cookie}
  HTTP.Cookies.readcookies(req.headers, matching)
end

"""
    set!(res::HTTP.Response, key::Union{String,Symbol}, value::Any, attributes::Dict) :: Response

Sets `value` under the `key` label on the `Cookie`.
"""
function set!(res::HTTP.Response, key::Union{String,Symbol}, value::Any, attributes::Dict = Dict(); encrypted::Bool = true) :: HTTP.Response
  normalized_attrs = Dict{Symbol,Any}()
  for (k,v) in attributes
    normalized_attrs[Symbol(lowercase(string(k)))] = v
  end

  value = string(value)
  encrypted && (value = Genie.Encryption.encrypt(value))
  cookie = HTTP.Cookies.Cookie(string(key), value; normalized_attrs...)

  headers = Dict(res.headers)
  if haskey(headers, "Set-Cookie")
    headers["Set-Cookie"] *= HTTP.Cookies.String(cookie, false)
  else
    headers["Set-Cookie"] = HTTP.Cookies.String(cookie, false)
  end
  res.headers = [(k => v) for (k,v) in headers]

  res
end

"""
    todict(req::Request) :: Dict{String,String}

Extracts the `Cookie` and `Set-Cookie` data from the `Request` and `Response` objects and converts it into a dict.
"""
function todict(r::Union{HTTP.Request,HTTP.Response}) :: Dict{String,String}
  d = Dict{String,String}()
  headers = Dict(r.headers)

  if haskey(headers, "Cookie")
    for cookie in split(headers["Cookie"], ";")
      cookie_parts = split(cookie, "=")
      d[strip(cookie_parts[1])] = cookie_parts[2]
    end
  end

  if haskey(headers, "Set-Cookie")
    for cookie in split(headers["Set-Cookie"], ";")
      cookie_parts = split(cookie, "=")
      d[strip(cookie_parts[1])] = cookie_parts[2]
    end
  end

  d
end
const to_dict = todict

end


text:
struct None end
struct Just{T}
    value::T
end

Maybe{T} = Union{None, Just{T}} where {T}

maybe(f, m::None, default) = default
maybe(f, m::Just, default) = f(m.value)

isJust(::None) = false
isJust(::Just) = true

isNone(::None) = true
isNone(::Just) = false

fromMaybe(m::Just, default) = m.value
fromMaybe(::None, default) = default

function qisdefined(x::Symbol)
    :($(Expr(:isdefined, x)))
end

function qmaybe(x::Symbol)
    isdef = Expr(:isdefined, x)
    :($isdef ? $Just($x) : $None())
end

macro qmaybe(s)
    esc(qmaybe(s))
end


text:
abstract type AbstractGenomicData end

@units @description @with_kw struct BaseGenome <: AbstractGenomicData
    L_DNA::Array{Float64,1} = 1e6*ones(1)                      | bp    | "Genome size"
    rRNA::Array{Float64,1} = 10.0*ones(1)                              | "rRNA copy number"
    min_gentime::Array{Float64,1} = 1.0*ones(1)                | hr    | "Minimum generation time"
    transporter_distr::Array{Float64,2} = 1.0*ones(6,1)                | "Relative transporter gene frequency in genome"
    enzyme_distr::Array{Float64,1} = 1.0*ones(1)                       | "Relative hydrolase gene frequency in genome"
end

function genome_size_to_cell_volume(L_DNA::Array{Float64,1})
    # Kempes et al. (2016), Eq. 8
    v_N = 1.47e-27
    V_DNA = v_N*L_DNA
    D_0 = 3e-17
    β_D = 0.21
    V_c = (V_DNA/D_0).^(1/β_D) # m^3
end

function cell_volume_to_protein_volume(V_c::Array{Float64,1})
    # Kempes et al. (2016), Eq. 12
    P_0 = 3.42e-7
    β_p = 0.70
    V_p = P_0*V_c.^β_p # m^3
end

function cell_volume_to_ribosome_volume(V_c::Array{Float64,1})
    # Kempes et al. (2016), Eq. 13
    l_p = 975
    V_p = cell_volume_to_protein_volume(V_c)
    m_p = 5.81e-20
    d_p = 1.37e6
    v_p = m_p/d_p
    N_p = V_p/v_p
    ϕ = 6.20e-5
    η = 6.20e-5
    l_r = 4566
    r_r = 63
    μ_0 = 4e7
    β_B = 1.64
    μ = μ_0*V_c.^(β_B-1)
    N_r = @. l_p*N_p*(ϕ/μ + 1)/(r_r/μ - l_r*(η/μ + 1))
    v_r = 3.04e-24
    V_r = N_r*v_r # m^3
end

function cell_volume_to_mRNA_volume(V_c::Array{Float64,1})
    # Kempes et al. (2016), Eq. 18
    V_r = cell_volume_to_ribosome_volume(V_c)
    v_r = 3.04e-24
    N_r = V_r/v_r
    v_mRNA = 1.43e-24
    n_mRNA = 1.08
    V_mRNA = v_mRNA*n_mRNA*N_r # m^3
end

function cell_volume_to_tRNA_volume(V_c::Array{Float64,1})
    # Kempes et al. (2016), Eq. 17
    V_r = cell_volume_to_ribosome_volume(V_c)
    v_r = 3.04e-24
    N_r = V_r/v_r
    v_tRNA = 3.10e-26
    n_tRNA = 9.3
    V_tRNA = v_tRNA*n_tRNA*N_r # m^3
end

function cell_volume_to_envelope_volume(V_c::Array{Float64,1})
    # Kempes et al. (2016), Eq. 19
    r_c = (3*V_c/(4*π)).^(1/3)
    r_env = 40.5e-9      # 27.5 if gram +
    p_p = 0.149
    V_env = @. (V_c - 4/3*π*(r_c - r_env).^3)*(1-p_p) # m^3
end

function genome_size_to_rRNA_copy_number(L_DNA::Array{Float64,1})
    # Roller et al. (2016) - Supp. Fig. 1
    rRNA  = @. ceil(2^(L_DNA./1e6 - 3.0)/0.66)
end

@units @description struct PCellComposition{T<:AbstractGenomicData}
     Isolate::T                   | "Isolate defined by BaseGenome"
     V_cell::Array{Float64,1}  | m^3 | "Total cell volume"
     V_p::Array{Float64,1}     | m^3 | "Protein volume"
     V_r::Array{Float64,1}     | m^3 | "Ribosome volume"
     V_mRNA::Array{Float64,1}  | m^3 | "mRNA volume"
     V_tRNA::Array{Float64,1}  | m^3 | "tRNA volume"
     V_env::Array{Float64,1}   | m^3 | "cell envelope volume"

     function PCellComposition{T}(Isolate::T) where T<:AbstractGenomicData
         V_cell = genome_size_to_cell_volume(Isolate.L_DNA)
         V_p    = cell_volume_to_protein_volume(V_cell)
         V_r    = cell_volume_to_ribosome_volume(V_cell)
         V_mRNA = cell_volume_to_mRNA_volume(V_cell)
         V_tRNA = cell_volume_to_tRNA_volume(V_cell)
         V_env  = cell_volume_to_envelope_volume(V_cell)
         new(Isolate, V_cell, V_p, V_r, V_mRNA, V_tRNA, V_env)
     end
end

function cell_volume_to_dry_mass(V_c::Array{Float64,1})
    v_0 = 3.0e-17
    β_D = 0.21
    V_DNA = v_0*V_c.^β_D
    V_p = cell_volume_to_protein_volume(V_c)
    V_r = cell_volume_to_ribosome_volume(V_c)
    V_mRNA = cell_volume_to_mRNA_volume(V_c)
    V_tRNA = cell_volume_to_tRNA_volume(V_c)
    V_env = cell_volume_to_envelope_volume(V_c)
    d_DNA = 2e6
    d_p = 1.37e6
    d_r = 1.79e6
    d_mem = 1.05e6
    d_RNA = 2e6
    m_d = d_DNA*V_DNA + d_p*V_p + d_r*V_r + d_mem*V_env + d_RNA*V_mRNA + d_RNA*V_tRNA  # g
end

function cell_volume_to_cell_number_density(V_c::Array{Float64,1})
    # assuming 47% of dry mass is C (BNID 100649)
    m_d = cell_volume_to_dry_mass(V_c)
    M_C = 12.0111
    N_A = 6.022e23
    λ_B = M_C./(0.47*m_d*N_A)    # mol cells/mol C
end

function cell_volume_to_dry_mass_baseline(V_c::Array{Float64,1})
    v_0 = 3.0e-17
    β_D = 0.21
    V_DNA = v_0*V_c.^β_D
    V_env = cell_volume_to_envelope_volume(V_c)
    d_DNA = 2e6
    d_mem = 1.05e6
    m_d = d_DNA*V_DNA + d_mem*V_env  # g
end

function cell_volume_to_dry_mass_growth(V_c::Array{Float64,1})
    V_r = cell_volume_to_ribosome_volume(V_c)
    V_mRNA = cell_volume_to_mRNA_volume(V_c)
    V_tRNA = cell_volume_to_tRNA_volume(V_c)
    d_r = 1.79e6
    d_RNA = 2e6
    m_d =  d_r*V_r + d_RNA*V_mRNA + d_RNA*V_tRNA  # g
end

function reserve_yield_constant(p::PCellComposition)
    # [molE_C/molV_C,   molE_N/molV_C]
    m_cell = cell_volume_to_dry_mass(p.V_cell)
    m_baseline = cell_volume_to_dry_mass_baseline(p.V_cell)
    z = m_baseline./m_cell
    X_z = [0.43, 0.43]  # 0.143
    m_growth = cell_volume_to_dry_mass_growth(p.V_cell)
    g = m_growth./m_cell
    X_g = [0.37, 0.153]
    y_EV = zeros(size(X_z,1), size(z,1))
    for i in 1:size(z,1)
            y_EV[:,i] = @. g[i]*X_g/(z[i]*X_z)
    end
    return y_EV
end


text:
module TempleMirrorPortal

using ..Ahorn, Maple

const placements = Ahorn.PlacementDict(
    "Temple Mirror Portal" => Ahorn.EntityPlacement(
        Maple.TempleMirrorPortal
    )
)

frameSprite = "objects/temple/portal/portalframe.png"
curtainSprite = "objects/temple/portal/portalcurtain00.png"
torchSprite = "objects/temple/portal/portaltorch00.png"

torchOffset = 90

function Ahorn.selection(entity::Maple.TempleMirrorPortal)
    x, y = Ahorn.position(entity)

    return Ahorn.coverRectangles([
        Ahorn.getSpriteRectangle(frameSprite, x, y),
        Ahorn.getSpriteRectangle(curtainSprite, x, y),
        Ahorn.getSpriteRectangle(torchSprite, x - torchOffset, y, jx=0.5, jy=0.75),
        Ahorn.getSpriteRectangle(torchSprite, x + torchOffset, y, jx=0.5, jy=0.75)
    ])
end

function Ahorn.render(ctx::Ahorn.Cairo.CairoContext, entity::Maple.TempleMirrorPortal, room::Maple.Room)
    Ahorn.drawSprite(ctx, frameSprite, 0, 0)
    Ahorn.drawSprite(ctx, curtainSprite, 0, 0)

    Ahorn.drawSprite(ctx, torchSprite, -torchOffset, 0, jx=0.5, jy=0.75)
    Ahorn.drawSprite(ctx, torchSprite, torchOffset, 0, jx=0.5, jy=0.75)
end

end


text:
using PyCall, PyPlot
# Use Conda.jl to install seaborn unless already installed: using Conda; Conda.add("seaborn")
@pyimport seaborn as sns
sns.set_style("whitegrid")
tips = sns.load_dataset("tips")
sns.violinplot(x="day", y="total_bill", hue="smoker", data=tips, palette="muted", split=true)
filename = "violin_plot_example.png"
savefig(filename)
println("Saved to file: ", filename)


text:
using LazyCat, Test

@testset "All tests" begin

    let A = [1 2
             3 4],
        B = [5 6
             7 8]

        @test lazy_cat(A, B) == [1 2
                                 3 4
                                 5 6
                                 7 8]
        @test lazy_cat(A, B, dim=2) == [1 2 5 6
                                        3 4 7 8]

        @test_throws LazyCat.NotImplementedError lazy_cat(A, B, dim=3)
    end

    let A = [1 2
             3 4],
        B = [5 6]

        @test lazy_cat(A, B) == [1 2
                                 3 4
                                 5 6]
        @test_throws ErrorException lazy_cat(A, B, dim=2)
    end

    let A = [1 2
             3 4],
        B = [5, 6]

        @test lazy_cat(A, B, dim=2) == [1 2 5
                                        3 4 6]
        @test_throws ErrorException lazy_cat(A, B)
    end

    let A = zeros(3, 3)
        B = zeros(3, 3, 2)

        @test_throws ErrorException lazy_cat(A, B, dim=1)
        C = lazy_cat(A, view(B, :, :, 1), dim=1)
        for i in 1:18
            C[i] = i
        end

        @test A == [1 7 13
                    2 8 14
                    3 9 15]
        @test B == cat([4 10 16
                        5 11 17
                        6 12 18], zeros(3, 3), dims=(3,))
    end
end

max_stars_repo_licenses: MIT Unlicense

max_issues_repo_licenses: MIT Unlicense

max_forks_repo_licenses: MIT Unlicense


text:
module IsotropicDamageTests

using Gridap
using LinearAlgebra
using Test

# max imposed displacement
const udx_max = 0.05

const L = 1

# Elastic model
const E = 2.1e4 # Pa
const ν = 0.3 # dim-less
const λ = (E*ν)/((1+ν)*(1-2*ν))
const μ = E/(2*(1+ν))
σe(ε) = λ*tr(ε)*one(ε) + 2*μ*ε # Pa
τ(ε) = sqrt(inner(ε,σe(ε))) # Pa^(1/2)

# Damage model
const σ_u = 5.5 # Pa
const r_0 = σ_u / sqrt(E) # Pa^(1/2)
const H = 0.1 # dim-less

function d(r)
  1 - q(r)/r
end

function q(r)
  r_0 + H*(r-r_0)
end

function new_state(r_in,d_in,ε_in)
  τ_in = τ(ε_in)
  if τ_in <= r_in
    r_out = r_in
    d_out = d_in
    damaged = false
  else
    r_out = τ_in
    d_out = d(r_out)
    damaged = true
  end
  damaged, r_out, d_out
end

function σ(ε_in,r_in,d_in)
  _, _, d_out = new_state(r_in,d_in,ε_in)
  (1-d_out)*σe(ε_in)
end

function dσ(dε_in,ε_in,state)
  damaged, r_out, d_out = state
  if ! damaged
    return (1-d_out)*σe(dε_in)
  else
    c_inc = ((q(r_out) - H*r_out)*inner(σe(ε_in),dε_in))/(r_out^3)
    return (1-d_out)*σe(dε_in) - c_inc*σe(ε_in)
  end
end

u(x) = VectorValue( udx_max*x[1]/L, -ν*udx_max*x[2]/L, -ν*udx_max*x[3]/L )

function main(;n,nsteps)

  domain = (0,L,0,L,0,L)
  partition = (n,n,n)
  model = CartesianDiscreteModel(domain,partition)

  labeling = get_face_labeling(model)
  add_tag_from_tags!(labeling,"ux0",[5,7,13,15,17,19,25])
  add_tag_from_tags!(labeling,"ux1",[2,4,6,8,14,16,18,20,26])
  add_tag_from_tags!(labeling,"uxyz0",[1])
  add_tag_from_tags!(labeling,"uxz0",[3])

  order = 1

  V = TestFESpace(
    model,
    ReferenceFE(lagrangian,VectorValue{3,Float64},order),
    labels = labeling,
    dirichlet_tags=["ux0","ux1","uxyz0","uxz0"],
    dirichlet_masks=[(true,false,false),(true,false,false),(true,true,true),(true,false,true)])

  degree = 2*order
  Ω = Triangulation(model)
  dΩ = Measure(Ω,degree)

  r = CellState(r_0,dΩ)
  d = CellState(0.0,dΩ)

  nls = NLSolver(show_trace=false, method=:newton)
  solver = FESolver(nls)

  function step(uh_in,factor)

    udx = factor*udx_max
    u0 = VectorValue(0.0,0.0,0.0)
    ud = VectorValue(udx,0.0,0.0)
    U = TrialFESpace(V,[u0,ud,u0,u0])

    res(u,v) = ∫( inner( ε(v), σ∘(ε(u),r,d) ) )*dΩ
    jac(u,du,v) = ∫( inner( ε(v), dσ∘(ε(du),ε(u),new_state∘(r,d,ε(u))) ) )*dΩ

    op = FEOperator(res,jac,U,V)

    free_values = get_free_values(uh_in)
    uh0 = FEFunction(U,free_values)

    uh_out, = solve!(uh0,solver,op)

    update_state!(new_state,r,d,ε(uh_out))

    uh_out
  end

  factors = collect(1:nsteps)*(1/nsteps)
  uh = zero(V)

  for (istep,factor) in enumerate(factors)
    uh = step(uh,factor)
  end

  e = uh - u

  e_l2 = sqrt(sum(∫(e⋅e)*dΩ))
  @test e_l2 < 1.0e-9

end

main(n=5,nsteps=10)

end # module


text:
""" Docstring """
module AA

export x, y

include("CC.jl")

immutable Part
    u
end

foo(x) = x+100

const x = 1009
y = 2005001

# Broken until JuliaLang#17618 is backported / Julia 0.6
## immutable ParametricTest{T}
##     x::T
## end

end


text:
using CSV

""" Game of Life iteration for the periodic boundary condition case"""
function game_it(A)
    M, N = size(A)
    j_l = j_r = 1
    i_u = i_d = 1
    B = zeros(Int64, M, N)
    for j in 1:N
        j == 1 ? j_l = N : j_l = j-1
        j == N ? j_r = 1 : j_r = j+1

        for i in 1:M
            i == 1 ? i_u = M : i_u = i-1
            i == M ? i_d = 1 : i_d = i+1

            sum_neigh = A[i_u,j_l] + A[i_u,j] + A[i_u,j_r] + A[i,j_l] + A[i,j_r] + A[i_d,j_l] + A[i_d,j] + A[i_d,j_r]
            if sum_neigh == 3 || (sum_neigh == 2 && A[i,j] == 1)
                B[i,j] = 1
            end
        end
    end
    return B
end

""" Game of Life iteration for the zero boundary condition case"""
function game_it_zero_bdry(A)
    M, N = size(A)
    B = zeros(Int64, M, N)
    for j in 2:N-1
        for i in 2:M-1
            sum_neigh = A[i-1,j-1] + A[i-1,j] + A[i-1,j+1] + A[i,j-1] + A[i,j+1] + A[i+1,j-1] + A[i+1,j] + A[i+1,j+1]
            if sum_neigh == 3 || (sum_neigh == 2 && A[i,j] == 1)
                B[i,j] = 1
            end
        end
    end
    return B
end

""" An auxiliary function for plotting the status of the game of life """
function plot_it(A)
    current_plot = heatmap(A,aspect_ratio=:equal,size = (400,400),grid=:none,axis = false,legend=nothing,color=:greys_r)

    # Plot a grid on top
    M, N = size(A)
    x1 = hcat([[0,N] for i in 0:M]...).+0.5
    y1 = hcat([[i,i] for i in 0:M]...).+0.5
    x2 = hcat([[i,i] for i in 0:N]...).+0.5
    y2 = hcat([[0,M] for i in 0:N]...).+0.5
    plot!(x1, y1,color=:lightgrey,linewidth=10/max(M,N))
    plot!(x2, y2,color=:lightgrey,linewidth=10/max(M,N))
    return current_plot
end

function gen_examples()

    # Check if the directory exists
    if !isdir("game_examples")
        mkdir("game_examples")
    end

    # Intro
    N = 35
    A = zeros(Int64, N, N)
    c = N ÷ 2+1
    A[[c-3,c+3],c-1:c+1] .= 1
    A[[c-2,c-1,c+1,c+2],[c-1,c+1]] .= 1
    CSV.write("game_examples/intro.csv", DataFrame(A))

    # Block
    A = zeros(Int64, 4, 4)
    A[2:3,2:3] .= 1
    CSV.write("game_examples/still_block.csv", DataFrame(A))

    # Hive
    A = zeros(Int64, 5, 6)
    A[[2,4],3:4] .= 1
    A[3,[2,5]] .= 1
    CSV.write("game_examples/still_hive.csv", DataFrame(A))

    # Tub
    A = zeros(Int64, 5, 5)
    A[[2,4],3] .= 1
    A[3,[2,4]] .= 1
    CSV.write("game_examples/still_tub.csv", DataFrame(A))

    # Blinker
    A = zeros(Int64, 5, 5)
    A[2:4,3] .= 1
    CSV.write("game_examples/osc_blinker.csv", DataFrame(A))

    # Beacon
    A = zeros(Int64, 6, 6)
    A[2:3,2:3] .= 1
    A[4:5,4:5] .= 1
    CSV.write("game_examples/osc_beacon.csv", DataFrame(A))

    # Ducks

    A = zeros(Int64, 7, 7)
    A[2,3:4] .= 1
    A[3,2:5] .= 1
    A[4,2:3] .= 1; A[4,5:6] .= 1;
    A[5,4:5] .= 1;

    function rotate(A)
        m, n = size(A)
        A = [A[n+1-i,j] for j in 1:m, i in 1:n]
        return A
    end

    N = 18
    B = zeros(Int64,N,N)
    B[1:7,1:7] .= A

    A = rotate(A); B[1:7,N-6:N] .= A[:,:];
    A = rotate(A); B[N-6:N,N-6:N] .= A[:,:]
    A = rotate(A); B[N-6:N,1:7] .= A[:,:]

    C = zeros(Int64, N+4, N+4)
    C[3:N+2,3:N+2] = B
    CSV.write("game_examples/final.csv", DataFrame(C))
end

max_stars_repo_name: ismedina/julia-scientific-computing

max_issues_repo_name: ismedina/julia-scientific-computing

max_forks_repo_name: ismedina/julia-scientific-computing