text:
const DSE = DocStringExtensions

include("templates.jl")
include("TestModule/M.jl")

# initialize a test repo in test/TestModule which is needed for some tests
function with_test_repo(f)
    repo = LibGit2.init(joinpath(@__DIR__, "TestModule"))
    LibGit2.add!(repo, "M.jl")
    sig = LibGit2.Signature("zeptodoctor", "zeptodoctor@zeptodoctor.com", round(time()), 0)
    LibGit2.commit(repo, "M.jl", committer = sig, author = sig)
    LibGit2.GitRemote(repo, "origin", "https://github.com/JuliaDocs/NonExistent.jl.git")
    try
        f()
    finally
        rm(joinpath(@__DIR__, "TestModule", ".git"); force = true, recursive = true)
    end
end

@testset "DocStringExtensions" begin
    @testset "Base assumptions" begin
        # The package heavily relies on type and docsystem-related methods and types from
        # Base, which are generally undocumented and their behaviour might change at any
        # time. This set of tests is tests and documents the assumptions the package makes
        # about them.
        #
        # The testset is not comprehensive -- i.e. DocStringExtensions makes use of
        # undocumented features that are not tested here. Should you come across anything
        # like that, please add a test here.
        #

        # Getting keyword arguments of a method.
        #
        # Used in src/utilities.jl for the keywords() function.
        #
        # The methodology is based on a snippet in Base at base/replutil.jl:572-576
        # (commit 3b45cdc9aab0). It uses the undocumented Base.kwarg_decl() function.
        @test isdefined(Base, :kwarg_decl)
        # Its signature is kwarg_decl(m::Method, kwtype::DataType). The second argument
        # should be the type of the kwsorter from the corresponding MethodTable.
        @test isa(methods(M.j_1), Base.MethodList)
        @test isdefined(methods(M.j_1), :mt)
        local mt = methods(M.j_1).mt
        @test isa(mt, Core.MethodTable)
        @test isdefined(mt, :kwsorter)
        # .kwsorter is not always defined -- namely, it seems when none of the methods
        # have keyword arguments:
        @test isdefined(methods(M.f).mt, :kwsorter) === false
        # M.j_1 has two methods. Fetch the single argument one..
        local m = which(M.j_1, (Any,))
        @test isa(m, Method)
        # .. which should have a single keyword argument, :y
        # Base.kwarg_decl returns a Vector{Any} of the keyword arguments.
        local kwargs = VERSION < v"1.4.0-DEV.215" ? Base.kwarg_decl(m, typeof(mt.kwsorter)) : Base.kwarg_decl(m)
        @test isa(kwargs, Vector)
        @test kwargs == [:y]
        # Base.kwarg_decl will return a Tuple{} for some reason when called on a method
        # that does not have any arguments
        m = which(M.j_1, (Any,Any)) # fetch the no-keyword method
        if VERSION < v"1.4.0-DEV.215"
            @test Base.kwarg_decl(m, typeof(methods(M.j_1).mt.kwsorter)) == Tuple{}()
        else
            @test Base.kwarg_decl(m) == []
        end
    end
    @testset "format" begin
        # Setup.
        doc = Docs.DocStr(Core.svec(), nothing, Dict())
        buf = IOBuffer()

        # Errors.
        @test_throws ErrorException DSE.format(nothing, buf, doc)

        @testset "imports & exports" begin
            # Module imports.
            doc.data = Dict(
                :binding => Docs.Binding(Main, :M),
                :typesig => Union{},
            )
            DSE.format(IMPORTS, buf, doc)
            str = String(take!(buf))
            @test occursin("\n  - `Base`\n", str)
            @test occursin("\n  - `Core`\n", str)

            # Module exports.
            DSE.format(EXPORTS, buf, doc)
            str = String(take!(buf))
            @test occursin("\n  - [`f`](@ref)\n", str)
        end

        @testset "type fields" begin
            doc.data = Dict(
                :binding => Docs.Binding(M, :T),
                :fields => Dict(
                    :a => "one",
                    :b => "two",
                ),
            )
            DSE.format(FIELDS, buf, doc)
            str = String(take!(buf))
            @test occursin("  - `a`", str)
            @test occursin("  - `b`", str)
            @test occursin("  - `c`", str)
            @test occursin("one", str)
            @test occursin("two", str)

            DSE.format(TYPEDFIELDS, buf, doc)
            str = String(take!(buf))
            @test occursin("  - `a::Any`", str)
            @test occursin("  - `b::Any`", str)
            @test occursin("  - `c::Any`", str)
            @test occursin("one", str)
            @test occursin("two", str)
        end

        @testset "method lists" begin
            doc.data = Dict(
                :binding => Docs.Binding(M, :f),
                :typesig => Tuple{Any},
                :module => M,
            )
            with_test_repo() do
                DSE.format(METHODLIST, buf, doc)
            end
            str = String(take!(buf))
            @test occursin("```julia", str)
            @test occursin("f(x)", str)
            @test occursin(joinpath("test", "TestModule", "M.jl"), str)
        end

        @testset "method signatures" begin
            doc.data = Dict(
                :binding => Docs.Binding(M, :f),
                :typesig => Tuple{Any},
                :module => M,
            )
            DSE.format(SIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            @test occursin("\nf(x)\n", str)
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :g),
                :typesig => Union{Tuple{}, Tuple{Any}},
                :module => M,
            )
            DSE.format(SIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            @test occursin("\ng()\n", str)
            @test occursin("\ng(x)\n", str)
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :g),
                :typesig => Union{Tuple{}, Tuple{Any}, Tuple{Any, Any}, Tuple{Any, Any, Any}},
                :module => M,
            )
            DSE.format(SIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            @test occursin("\ng()\n", str)
            @test occursin("\ng(x)\n", str)
            @test occursin("\ng(x, y)\n", str)
            @test occursin("\ng(x, y, z; kwargs...)\n", str)
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :h_4),
                :typesig => Union{Tuple{Any, Int, Any}},
                :module => M,
            )
            DSE.format(SIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            @test occursin("\nh_4(x, _, z)\n", str)
            @test occursin("\n```\n", str)
        end

        @testset "method signatures with types" begin
            doc.data = Dict(
                :binding => Docs.Binding(M, :h_1),
                :typesig => Tuple{M.A},
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            f = str -> replace(str, " " => "")
            str = f(str)
            if Sys.iswindows()
                @test occursin(f("h_1(x::Union{Array{T,4}, Array{T,3}} where T) -> Union{Array{T,4}, Array{T,3}} where T"), str)
            else
                @test occursin(f("h_1(x::Union{Array{T,3}, Array{T,4}} where T) -> Union{Array{T,3}, Array{T,4}} where T"), str)
            end
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :h),
                :typesig => Tuple{Int, Int, Int},
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            if typeof(1) === Int64
                @test occursin("\nh(x::Int64, y::Int64, z::Int64; kwargs...) -> Int64\n", str)
            else
                @test occursin("\nh(x::Int32, y::Int32, z::Int32; kwargs...) -> Int32\n", str)
            end
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :h),
                :typesig => Tuple{Int},
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            if typeof(1) === Int64
                @test occursin("\nh(x::Int64) -> Int64\n", str)
            else
                @test occursin("\nh(x::Int32) -> Int32\n", str)
            end
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :k_1),
                :typesig => Union{Tuple{String}, Tuple{String, T}, Tuple{String, T, T}, Tuple{T}} where T <: Number,
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            @test occursin("\nk_1(x::String) -> String\n", str)
            @test occursin("\nk_1(x::String, y::T<:Number) -> String\n", str)
            @test occursin("\nk_1(x::String, y::T<:Number, z::T<:Number) -> String\n", str)
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :k_2),
                :typesig => (Union{Tuple{String, U, T}, Tuple{T}, Tuple{U}} where T <: Number) where U <: Complex,
                :module => M,
            )

            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            @test occursin("k_2(x::String, y::U<:Complex, z::T<:Number) -> String", str)
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :k_3),
                :typesig => (Union{Tuple{Any, T, U}, Tuple{U}, Tuple{T}} where U <: Any) where T <: Any,
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            @test occursin("\nk_3(x, y::T, z::U) -> Any\n", str)
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :k_4),
                :typesig => Union{Tuple{String}, Tuple{String, Int}},
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            if VERSION > v"1.3.0"
                @test occursin("\nk_4(::String)\n", str)
                if typeof(1) === Int64
                    @test occursin("\nk_4(::String, ::Int64)\n", str)
                else
                    @test occursin("\nk_4(::String, ::Int32)\n", str)
                end
            else
                # TODO: remove this test when julia 1.0.0 support is dropped.
                # older versions of julia seem to return this
                # str = "\n```julia\nk_4(#temp#::String)\nk_4(#temp#::String, #temp#::Int64)\n\n```\n\n"
                @test occursin("\nk_4", str)
            end
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :k_5),
                :typesig => Union{Tuple{Type{T}, String}, Tuple{Type{T}, String, Union{Nothing, Function}}, Tuple{T}} where T <: Number,
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            if VERSION > v"1.3.0"
                @test occursin("\nk_5(::Type{T<:Number}, x::String) -> String\n", str)
                @test occursin("\nk_5(::Type{T<:Number}, x::String, func::Union{Nothing, Function}) -> String\n", str)
                @test occursin("\n```\n", str)
            else
                # TODO: remove this test when julia 1.0.0 support is dropped.
                # older versions of julia seem to return this
                # str = "\n```julia\nk_5(#temp#::Type{T<:Number}, x::String) -> String\nk_5(#temp#::Type{T<:Number}, x::String, func::Union{Nothing, Function}) -> String\n\n```\n\n"
                @test occursin("\nk_5", str)
            end

            doc.data = Dict(
                :binding => Docs.Binding(M, :k_6),
                :typesig => Union{Tuple{Vector{T}}, Tuple{T}} where T <: Number,
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            f = str -> replace(str, " " => "")
            str = String(take!(buf))
            str = f(str)
            @test occursin("\n```julia\n", str)
            @test occursin(f("\nk_6(x::Array{T<:Number,1}) -> Array{T<:Number,1}\n"), str)
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :k_7),
                :typesig => Union{Tuple{Union{T, Nothing}}, Tuple{Union{T, Nothing}, T}, Tuple{T}} where T <: Integer,
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            @test occursin("\nk_7(x::Union{Nothing, T<:Integer}) -> Union{Nothing, Integer}\n", str)
            @test occursin("\nk_7(x::Union{Nothing, T<:Integer}, y::T<:Integer) -> Union{Nothing, T<:Integer}\n", str)
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :k_8),
                :typesig => Union{Tuple{Any}},
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            @test occursin("\nk_8(x) -> Any\n", str)
            @test occursin("\n```\n", str)

            doc.data = Dict(
                :binding => Docs.Binding(M, :k_9),
                :typesig => Union{Tuple{T where T}},
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test occursin("\n```julia\n", str)
            @test occursin("\nk_9(x) -> Any\n", str)
            @test occursin("\n```\n", str)

            @static if VERSION > v"1.5-" # see JuliaLang/#40405

                doc.data = Dict(
                    :binding => Docs.Binding(M, :k_11),
                    :typesig => Union{Tuple{Int, Vararg{Any}}},
                    :module => M,
                )
                DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
                str = String(take!(buf))
                @test occursin("\n```julia\n", str)
                @test occursin("\nk_11(x::Int64, xs...) -> Int64\n", str)
                @test occursin("\n```\n", str)

                doc.data = Dict(
                    :binding => Docs.Binding(M, :k_12),
                    :typesig => Union{Tuple{Int, Vararg{Real}}},
                    :module => M,
                )
                DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
                str = String(take!(buf))
                @test occursin("\n```julia\n", str)
                @test occursin("\nk_12(x::Int64, xs::Real...) -> Int64\n", str)
                @test occursin("\n```\n", str)

            end

            doc.data = Dict(
                :binding => Docs.Binding(M, :k_10),
                :typesig => Union{Tuple{T}, Tuple{T}} where T,
                :module => M,
            )
            DSE.format(DSE.TYPEDSIGNATURES, buf, doc)
            str = String(take!(buf))
            @test_broken occursin("\n```julia\n", str)
            @test_broken occursin("\nk_10(x::T) -> Any\n", str)
            @test_broken occursin("\n```\n", str)
        end

        @testset "function names" begin
            doc.data = Dict(
                :binding => Docs.Binding(M, :f),
                :typesig => Tuple{Any},
                :module => M,
            )
            DSE.format(FUNCTIONNAME, buf, doc)
            str = String(take!(buf))
            @test str == "f"
        end

        @testset "type definitions" begin
            doc.data = Dict(
                :binding => Docs.Binding(M, :AbstractType1),
                :typesig => Union{},
                :module => M,
            )
            DSE.format(TYPEDEF, buf, doc)
            str = String(take!(buf))
            @test str == "\n```julia\nabstract type AbstractType1 <: Integer\n```\n\n"

            doc.data = Dict(
                :binding => Docs.Binding(M, :AbstractType2),
                :typesig => Union{},
                :module => M,
            )
            DSE.format(TYPEDEF, buf, doc)
            str = String(take!(buf))
            @test str == "\n```julia\nabstract type AbstractType2{S, T<:Integer} <: Integer\n```\n\n"

            doc.data = Dict(
                :binding => Docs.Binding(M, :CustomType),
                :typesig => Union{},
                :module => M,
            )
            DSE.format(TYPEDEF, buf, doc)
            str = String(take!(buf))
            @test str == "\n```julia\nstruct CustomType{S, T<:Integer} <: Integer\n```\n\n"

            doc.data = Dict(
                :binding => Docs.Binding(M, :BitType8),
                :typesig => Union{},
                :module => M,
            )
            DSE.format(TYPEDEF, buf, doc)
            str = String(take!(buf))
            @test str == "\n```julia\nprimitive type BitType8 8\n```\n\n"

            doc.data = Dict(
                :binding => Docs.Binding(M, :BitType32),
                :typesig => Union{},
                :module => M,
            )
            DSE.format(TYPEDEF, buf, doc)
            str = String(take!(buf))
            @test str == "\n```julia\nprimitive type BitType32 <: Real 32\n```\n\n"
        end

        @testset "README/LICENSE" begin
            doc.data = Dict(:module => DocStringExtensions)
            DSE.format(README, buf, doc)
            str = String(take!(buf))
            @test occursin("*Extensions for Julia's docsystem.*", str)
            DSE.format(LICENSE, buf, doc)
            str = String(take!(buf))
            @test occursin("MIT \"Expat\" License", str)
        end
    end
    @testset "templates" begin
        let fmt = expr -> Markdown.plain(eval(:(@doc $expr)))
            @test occursin("(DEFAULT)", fmt(:(TemplateTests.K)))
            @test occursin("(TYPES)", fmt(:(TemplateTests.T)))
            @test occursin("(TYPES)", fmt(:(TemplateTests.S)))
            @test occursin("(METHODS, MACROS)", fmt(:(TemplateTests.f)))
            @test occursin("(METHODS, MACROS)", fmt(:(TemplateTests.g)))
            @test occursin("(METHODS, MACROS)", fmt(:(TemplateTests.h)))
            @test occursin("(METHODS, MACROS)", fmt(:(TemplateTests.@m)))

            @test occursin("(DEFAULT)", fmt(:(TemplateTests.InnerModule.K)))
            @test occursin("(DEFAULT)", fmt(:(TemplateTests.InnerModule.T)))
            @test occursin("field docs for x", fmt(:(TemplateTests.InnerModule.T)))
            @test occursin("(METHODS, MACROS)", fmt(:(TemplateTests.InnerModule.f)))
            @test occursin("(MACROS)", fmt(:(TemplateTests.InnerModule.@m)))

            @test occursin("(TYPES)", fmt(:(TemplateTests.OtherModule.T)))
            @test occursin("(MACROS)", fmt(:(TemplateTests.OtherModule.@m)))
            @test fmt(:(TemplateTests.OtherModule.f)) == "method `f`\n"
        end
    end
    @testset "utilities" begin
        @testset "keywords" begin
            @test DSE.keywords(M.T, first(methods(M.T))) == Symbol[]
            @test DSE.keywords(M.K, first(methods(M.K))) == [:a]
            @test DSE.keywords(M.f, first(methods(M.f))) == Symbol[]
            let f = (() -> ()),
                m = first(methods(f))
                @test DSE.keywords(f, m) == Symbol[]
            end
            let f = ((a) -> ()),
                m = first(methods(f))
                @test DSE.keywords(f, m) == Symbol[]
            end
            let f = ((; a = 1) -> ()),
                m = first(methods(f))
                @test DSE.keywords(f, m) == [:a]
            end
            let f = ((; a = 1, b = 2) -> ()),
                m = first(methods(f))
                @test DSE.keywords(f, m) == [:a, :b]
            end
            let f = ((; a...) -> ()),
                m = first(methods(f))
                @test DSE.keywords(f, m) == [Symbol("a...")]
            end
            # Tests for #42
            let f = M.i_1, m = first(methods(f))
                @test DSE.keywords(f, m) == [:y]
            end
            let f = M.i_2, m = first(methods(f))
                @test DSE.keywords(f, m) == [:y]
            end
            let f = M.i_3, m = first(methods(f))
                @test DSE.keywords(f, m) == [:y]
            end
            let f = M.i_4, m = first(methods(f))
                @test DSE.keywords(f, m) == [:y, :z]
            end
        end
        @testset "arguments" begin
            @test DSE.arguments(first(methods(M.T))) == [:a, :b, :c]
            @test DSE.arguments(first(methods(M.K))) == Symbol[]
            @test DSE.arguments(first(methods(M.f))) == [:x]
            let m = first(methods(() -> ()))
                @test DSE.arguments(m) == Symbol[]
            end
            let m = first(methods((a) -> ()))
                @test DSE.arguments(m) == [:a]
            end
            let m = first(methods((; a = 1) -> ()))
                @test DSE.arguments(m) == Symbol[]
            end
            let m = first(methods((x; a = 1, b = 2) -> ()))
                @test DSE.arguments(m) == Symbol[:x]
            end
            let m = first(methods((; a...) -> ()))
                @test DSE.arguments(m) == Symbol[]
            end
        end
        @testset "printmethod" begin
            let b = Docs.Binding(M, :T),
                f = M.T,
                m = first(methods(f))
                @test DSE.printmethod(b, f, m) == "T(a, b, c)"
            end
            let b = Docs.Binding(M, :K),
                f = M.K,
                m = first(methods(f))
                @test DSE.printmethod(b, f, m) == "K(; a)"
            end
            let b = Docs.Binding(M, :f),
                f = M.f,
                m = first(methods(f))
                @test DSE.printmethod(b, f, m) == "f(x)"
            end
            let b = Docs.Binding(Main, :f),
                f = () -> (),
                m = first(methods(f))
                @test DSE.printmethod(b, f, m) == "f()"
            end
            let b = Docs.Binding(Main, :f),
                f = (a) -> (),
                m = first(methods(f))
                @test DSE.printmethod(b, f, m) == "f(a)"
            end
            let b = Docs.Binding(Main, :f),
                f = (; a = 1) -> (),
                m = first(methods(f))
                @test DSE.printmethod(b, f, m) == "f(; a)"
            end
            let b = Docs.Binding(Main, :f),
                f = (; a = 1, b = 2) -> (),
                m = first(methods(f))
                # Keywords are not ordered, so check for both combinations.
                @test DSE.printmethod(b, f, m) in ("f(; a, b)", "f(; b, a)")
            end
            let b = Docs.Binding(Main, :f),
                f = (; a...) -> (),
                m = first(methods(f))
                @test DSE.printmethod(b, f, m) == "f(; a...)"
            end
            let b = Docs.Binding(Main, :f),
                f = (; a = 1, b = 2, c...) -> (),
                m = first(methods(f))
                # Keywords are not ordered, so check for both combinations.
                @test DSE.printmethod(b, f, m) in ("f(; a, b, c...)", "f(; b, a, c...)")
            end
        end
        @testset "getmethods" begin
            @test length(DSE.getmethods(M.f, Union{})) == 1
            @test length(DSE.getmethods(M.f, Tuple{})) == 0
            @test length(DSE.getmethods(M.f, Union{Tuple{}, Tuple{Any}})) == 1
            @test length(DSE.getmethods(M.h_3, Tuple{M.A{Int}})) == 1
            @test length(DSE.getmethods(M.h_3, Tuple{Array{Int, 3}})) == 1
            @test length(DSE.getmethods(M.h_3, Tuple{Array{Int, 1}})) == 0
        end
        @testset "methodgroups" begin
            @test length(DSE.methodgroups(M.f, Tuple{Any}, M)) == 1
            @test length(DSE.methodgroups(M.f, Tuple{Any}, M)[1]) == 1
            @test length(DSE.methodgroups(M.h_1, Tuple{M.A}, M)) == 1
            @test length(DSE.methodgroups(M.h_1, Tuple{M.A}, M)[1]) == 1
            @test length(DSE.methodgroups(M.h_2, Tuple{M.A{Int}}, M)) == 1
            @test length(DSE.methodgroups(M.h_2, Tuple{M.A{Int}}, M)[1]) == 1
            @test length(DSE.methodgroups(M.h_3, Tuple{M.A}, M)[1]) == 1
        end
        @testset "alltypesigs" begin
            @test DSE.alltypesigs(Union{}) == Any[]
            @test DSE.alltypesigs(Union{Tuple{}}) == Any[Tuple{}]
            @test DSE.alltypesigs(Tuple{}) == Any[Tuple{}]

            # TODO: Clean me up
            T = Type{T} where {T}
            @test DSE.alltypesigs(T) ==
                Base.rewrap_unionall.(DSE.uniontypes(Base.unwrap_unionall(T)), T)
        end
        @testset "groupby" begin
            let groups = DSE.groupby(Int, Vector{Int}, collect(1:10)) do each
                    mod(each, 3), each
                end
                @test groups == Pair{Int, Vector{Int}}[
                    0 => [3, 6, 9],
                    1 => [1, 4, 7, 10],
                    2 => [2, 5, 8],
                ]
            end
        end
        @testset "url" begin
            @test !isempty(DSE.url(first(methods(sin))))
            with_test_repo() do
                @test occursin("github.com/JuliaDocs/NonExistent", DSE.url(first(methods(M.f))))
                @test occursin("github.com/JuliaDocs/NonExistent", DSE.url(first(methods(M.K))))
            end
        end
        @testset "comparemethods" begin
            let f = first(methods(M.f)),
                g = first(methods(M.g))
                @test !DSE.comparemethods(f, f)
                @test DSE.comparemethods(f, g)
                @test !DSE.comparemethods(g, f)
            end
        end
    end
end

DSE.parsedocs(DSE)


text:
using Pixell
using Test, DelimitedFiles
import Pixell: degree, arcminute

@testset "Enmap geometry" begin
    for W in (Pixell.WCS.WCSTransform, CarClenshawCurtis{Float64})
        shape, wcs = fullsky_geometry(W, deg2rad(1 / 60))
        @test collect(wcs.cdelt) ≈ [-0.016666666666666666, 0.016666666666666666]
        @test collect(wcs.crpix) ≈ [10800.5, 5401.0]
        @test collect(wcs.crval) ≈ [0.008333333333333333, 0.0]

        shape, wcs = fullsky_geometry(W, deg2rad(1 / 61))
        @test collect(wcs.cdelt) ≈ [-0.01639344262295082, 0.01639344262295082]
        @test collect(wcs.crpix) ≈ [10980.5, 5491.0]
        @test collect(wcs.crval) ≈ [0.00819672131147541, 0.0]

        shape, wcs = fullsky_geometry(W, deg2rad(5); dims=(3,))
        @test shape == (72, 37, 3)

        box = [10  -10;           # RA
               -5    5] * degree  # DEC
        shape, wcs = geometry(W, box, 0.5 * arcminute)
        @test shape == (2400, 1200)
        @test collect(wcs.cdelt) ≈ [-0.008333333333333333,  0.008333333333333333]
        @test collect(wcs.crpix) == [1201, 601]
        @test collect(wcs.crval) == [0.0, 0.0]

        box = [11  -10;           # RA
               -6    5] * degree  # DEC
        shape, wcs = geometry(W, box, 0.5 * arcminute)
        @test shape == (2520, 1320)
        @test collect(wcs.cdelt) ≈ [-0.008333333333333333,  0.008333333333333333]
        @test collect(wcs.crpix) ≈ [1261, 721]
        @test collect(wcs.crval) ≈ [0.5, 0.0]

        box = [10   -4;           # RA
               -3    5] * degree  # DEC
        shape, wcs = geometry(W, box, 0.5 * arcminute)
        @test shape == (1680, 960)
        @test collect(wcs.crpix) ≈ [841, 361]
        @test collect(wcs.crval) ≈ [3.0, 0.0]
    end
end

##
wrap(ra_dec_vec) = [mod(ra_dec_vec[1], 2π), mod(ra_dec_vec[2], π)]
@testset "Enmap sky2pix and pix2sky" begin
    for W in (Pixell.WCS.WCSTransform, CarClenshawCurtis{Float64})
        shape, wcs = fullsky_geometry(W, deg2rad(1))
        m = Enmap(rand(shape...), wcs)
        # in this test, wrap to angles in [0, 2π] and [0, π] for RA and DEC
        @test [3.12413936, -1.55334303] ≈ collect(pix2sky(m, [2.0, 2.0]))
        @test [2.96705973, -1.79768913] ≈ collect(pix2sky(m, [11.0, -12.0]))
        @test [2.44346095, -2.0943951] ≈ collect(pix2sky(m, [41.0, -29.0]))
        @test [1.0, 0.0] ≈ collect(sky2pix(m, pix2sky(m, [1.0, 0.0])))
        @test [13., 7.] ≈ collect(sky2pix(m, pix2sky(m, [13., 7.])))

        # test passing a vector
        @test [[1.0], [0.0]] ≈ collect(sky2pix(m, pix2sky(m, [1.0], [0.0])...))
        @test [[13.], [7.]] ≈ collect(sky2pix(m, pix2sky(m, [13.], [7.])...))

        # try some crazy angles
        @test [1.0, 0.0] ≈ collect(sky2pix(m, pix2sky(m, [1.0, 0.0]) .+ (2π, 6π)))
        @test [13., 7.] ≈ collect(sky2pix(m, pix2sky(m, [13., 7.]) .+ (12π, 16π)))

        # check our custom implementations
        pixcoords = π .* rand(2, 1024)
        skycoords = pix2sky(m, pixcoords; safe=false)
        shape, wcs_generic = fullsky_geometry(Pixell.WCS.WCSTransform, deg2rad(1))
        @test skycoords ≈ Pixell.WCS.pix_to_world(wcs_generic, pixcoords) .* (π/180)
        skycoords .= 0.0
        pix2sky!(m, pixcoords, skycoords; safe=false)
        @test skycoords ≈ Pixell.WCS.pix_to_world(wcs_generic, pixcoords) .* (π/180)

        skycoords = π .* rand(2, 1024)
        pixcoords = sky2pix(m, skycoords; safe=false)
        @test pixcoords ≈ Pixell.WCS.world_to_pix(wcs_generic, skycoords .* (180/π))
        pixcoords .= 0.0
        sky2pix!(m, skycoords, pixcoords; safe=false)
        @test pixcoords ≈ Pixell.WCS.world_to_pix(wcs_generic, skycoords .* (180/π))

        box = [10   -10;           # RA
            -5     5] * degree  # DEC
        shape, wcs = geometry(W, box, 1 * degree)
        m = Enmap(ones(shape), wcs)
        @test [sky2pix(m, deg2rad(ra), 0.0; safe=true)[1]
            for ra in 178:182] ≈ [-167., -168., -169.,  190.,  189.]
    end
end

##
@testset "Enmap sky2pix and pix2sky WCSlib fallbacks" begin
    shape, wcs = fullsky_geometry(Pixell.WCS.WCSTransform, deg2rad(1))
    m = Enmap(rand(shape...), wcs)
    # in this test, wrap to angles in [0, 2π] and [0, π] for RA and DEC
    @test [3.12413936, -1.55334303] ≈ collect(pix2sky(m, [2.0, 2.0]))
    @test [2.96705973, -1.79768913] ≈ collect(pix2sky(m, [11.0, -12.0]))
    @test [2.44346095, -2.0943951] ≈ collect(pix2sky(m, [41.0, -29.0]))
    @test [1.0, 0.0] ≈ collect(sky2pix(m, pix2sky(m, [1.0, 0.0])))
    @test [13., 7.] ≈ collect(sky2pix(m, pix2sky(m, [13., 7.])))

    @test [1.0, 0.0] ≈ collect(sky2pix(m, pix2sky(m, [1.0, 0.0]) .+ (2π, 6π)))
    @test [13., 7.] ≈ collect(sky2pix(m, pix2sky(m, [13., 7.]) .+ (12π, 16π)))

    # check our custom implementations
    pixcoords = π .* rand(2, 1024)
    skycoords = pix2sky(m, pixcoords; safe=false)
    shape, wcs_generic = fullsky_geometry(Pixell.WCS.WCSTransform, deg2rad(1))
    @test skycoords ≈ Pixell.WCS.pix_to_world(wcs_generic, pixcoords) .* (π/180)
    skycoords .= 0.0
    pix2sky!(m, pixcoords, skycoords; safe=false)
    @test skycoords ≈ Pixell.WCS.pix_to_world(wcs_generic, pixcoords) .* (π/180)

    skycoords = π .* rand(2, 1024)
    pixcoords = sky2pix(m, skycoords; safe=false)
    @test pixcoords ≈ Pixell.WCS.world_to_pix(wcs_generic, skycoords .* (180/π))
    pixcoords .= 0.0
    sky2pix!(m, skycoords, pixcoords; safe=false)
    @test pixcoords ≈ Pixell.WCS.world_to_pix(wcs_generic, skycoords .* (180/π))

    box = [10   -10;           # RA
           -5     5] * degree  # DEC
    shape, wcs = geometry(CarClenshawCurtis, box, 1 * degree)
    m = Enmap(ones(shape), wcs)
    @test [sky2pix(m, deg2rad(ra), 0.0; safe=true)[1]
        for ra in 178:182] ≈ [-167., -168., -169.,  190.,  189.]

end

##
@testset "sky2pix every single pixel" begin
    box = [10   -10;           # RA
        -5     5] * degree  # DEC
    shape, wcs = geometry(CarClenshawCurtis, box, 1 * degree)
    m = Enmap(ones(shape), wcs)
    for i in 1:shape[1]
        for j in 1:shape[2]
            ra, dec = pix2sky(m, i, j)
            ra_unsafe, dec_unsafe = pix2sky(m, i, j; safe=false)
            @test ra ≈ ra_unsafe
            @test dec ≈ dec_unsafe

            ra_pix, dec_pix = sky2pix(m, ra, dec)
            ra_pix_unsafe, dec_pix_unsafe = sky2pix(m, ra, dec; safe=false)

            @test ra_pix ≈ ra_pix_unsafe
            @test dec_pix ≈ dec_pix_unsafe
        end
    end

    box = [179   -179;           # RA
           -89     89] * degree  # DEC
    shape, wcs = geometry(CarClenshawCurtis, box, 1 * degree)
    m = Enmap(ones(shape), wcs)
    for i in 1:shape[1]
        for j in 1:shape[2]
            ra, dec = pix2sky(m, i, j)
            ra_unsafe, dec_unsafe = pix2sky(m, i, j; safe=false)
            @test ra ≈ ra_unsafe
            @test dec ≈ dec_unsafe
            @test -π ≤ ra ≤ π
            @test -π/2 ≤ dec ≤ π/2

            ra_pix, dec_pix = sky2pix(m, ra, dec)
            ra_pix_unsafe, dec_pix_unsafe = sky2pix(m, ra, dec; safe=false)

            @test ra_pix ≈ ra_pix_unsafe
            @test dec_pix ≈ dec_pix_unsafe
            @test 1 ≤ ra_pix ≤ shape[1]
            @test 1 ≤ dec_pix ≤ shape[2]
        end
    end

    # determine if safe angles are on the sky
    shape, wcs = fullsky_geometry(deg2rad(1))
    m = Enmap(ones(shape), wcs)
    for i in 1:shape[1]
        for j in 1:shape[2]
            ra, dec = pix2sky(m, i, j)
            ra_unsafe, dec_unsafe = pix2sky(m, i, j; safe=false)
            @test -π ≤ ra ≤ π
            @test -π/2 ≤ dec ≤ π/2

            ra_pix, dec_pix = sky2pix(m, ra, dec)
            @test 1 ≤ ra_pix ≤ shape[1]
            @test 1 ≤ dec_pix ≤ shape[2]
            ra_pix, dec_pix = sky2pix(m, ra_unsafe, dec_unsafe)
            @test 1 ≤ ra_pix ≤ shape[1]
            @test 1 ≤ dec_pix ≤ shape[2]
        end
    end

end

##
@testset "nonallocating WCS info utilities" begin
    shape, wcs = fullsky_geometry(deg2rad(1))
    @test all(Pixell.getcrpix(wcs) .== collect(wcs.crpix))
    @test all(Pixell.getcrval(wcs) .== collect(wcs.crval))
    @test all(Pixell.getcdelt(wcs) .== collect(wcs.cdelt))
end

##
@testset "slice_geometry" begin
    for W in (Pixell.WCS.WCSTransform, CarClenshawCurtis{Float64})
        shape0, wcs0 = fullsky_geometry(W, deg2rad(1))
        shape, wcs = slice_geometry(shape0, wcs0, 1:3, 11:-1:3)
        @test (3, 9) == shape
        @test [-1.0, -1.0] ≈ collect(wcs.cdelt)
        @test [180.5, -79.0] ≈ collect(wcs.crpix)
        @test [0.5, 0.0] ≈ collect(wcs.crval)

        shape, wcs = slice_geometry(shape0, wcs0, 2:shape0[1], 6:11)
        @test (359, 6) == shape
        @test [-1.0, 1.0] ≈ collect(wcs.cdelt)
        @test [179.5, 86.0] ≈ collect(wcs.crpix)
        @test [0.5, 0.0] ≈ collect(wcs.crval)

        shape, wcs = slice_geometry(shape0, wcs0, 2:2:(shape0[1]-1),1:11)
        @test (179, 11) == shape
        @test [-2.0, 1.0] ≈ collect(wcs.cdelt)
        @test [90.0, 91.0] ≈ collect(wcs.crpix)
        @test [0.5, 0.0] ≈ collect(wcs.crval)

        shape, wcs = slice_geometry(shape0, wcs0, 23:-4:6, 1:3:28)
        @test (5, 10) == shape
        @test [4.0, 3.0] ≈ collect(wcs.cdelt)
        @test [-38.75, 30.666666666666668] ≈ collect(wcs.crpix)
        @test [0.5, 0.0] ≈ collect(wcs.crval)

        shape, wcs = slice_geometry(shape0, wcs0, 3:3, 1:3:28)
        @test (1, 10) == shape
        @test [-1.0, 3.0] ≈ collect(wcs.cdelt)
        @test [178.5, 30.666666666666668] ≈ collect(wcs.crpix)
        @test [0.5, 0.0] ≈ collect(wcs.crval)
    end
end

##
@testset "pixel skyareas" begin
    for W in (Pixell.WCS.WCSTransform, CarClenshawCurtis{Float64})
        shape, wcs = fullsky_geometry(W, deg2rad(1))
        @test skyarea(shape, wcs) ≈ 4π

        shape′, wcs′ = slice_geometry(shape, wcs, 9:-1:3, 1:2)
        @test skyarea(shape′, wcs′) ≈ 4.1865652086145036e-05

        box = [10   -10;           # RA
               -5     5] * degree  # DEC
        shape, wcs = geometry(CarClenshawCurtis, box, (1/60) * degree)
        @test skyarea(shape, wcs) ≈ 0.06084618627514243
    end
end

@testset "pixareamap" begin
    box = [10  -10;           # RA
           -5    5] * Pixell.degree  # DEC

    boxgeom = geometry(CarClenshawCurtis{Float64}, box, 5. * Pixell.arcminute)
    fullgeom = fullsky_geometry(π/180)

    pm_py_full = readdlm("data/fullsky_pixareas.dat")
    pm_py_box = readdlm("data/box_pixareas.dat")

    for i in 1:2
        # test passing shape, wcs info
        shape, wcs = (fullgeom, boxgeom)[i]
        pm_py = (pm_py_full, pm_py_box)[i]

        pm = pixareamap(shape, wcs)
        @test sum(abs.(pm[1,:] .- pm_py)) < 100eps()

        pm = pixareamap(shape, wcs)
        @test sum(abs.(pm[1,:] .- pm_py)) < 100eps()

        # test passing an Enmap
        m = Enmap(zeros(shape), wcs)
        pm = pixareamap(m)
        @test sum(abs.(pm[1,:] .- pm_py)) < 100eps()
        fill!(pm, 0.0)
        pm = pixareamap!(m)
        @test sum(abs.(pm[1,:] .- pm_py)) < 100eps()
    end
end

ext: jl


text:
"""
    Cluster(u₁::Real,u₂::Real,position::Vector{<:Int},value::Vector{<:Real})

Cluster type.
"""
struct Cluster
    "first threshold"
    u₁::Real
    "second threshold"
    u₂::Real
    "positions of clustered exceedences"
    position::Vector{<:Int}
    "values of clustered exceedences"
    value::Vector{<:Real}

    function Cluster(u₁::Real,u₂::Real,position::Vector{<:Int},value::Vector{<:Real})
        @assert u₁ >= u₂ "the second threshold should not be higher than the first one."
        @assert length(position) == length(value) "the vectors of the clustered exceedances positions and the values should be of the same length."

        return new(u₁,u₂,position,value)
    end
end

Base.Broadcast.broadcastable(obj::Cluster) = Ref(obj)

"""
    getcluster(y::Vector{<:Real}, u₁::Real, u₂::Real)

Extract the clusters from vector `y`.

A cluster is defined as a sequence of values higher than threshold u₂ with at
least a value higher than threshold u₁.

See also [`Cluster`](@ref).

"""
function getcluster(y::Vector{<:Real}, u₁::Real, u₂::Real)::Vector{Cluster}

    @assert u₁ >= u₂ "the second threshold should not be higher than the first one."

    n = length(y)

    exceedancePosition = findall(y .> u₁)

    clusterEnd = 0

    cluster = Vector{Cluster}()

    for i in exceedancePosition

            if i > clusterEnd

               j = 1

                while (i-j) > 0
                    if y[i-j] > u₂
                        j += 1
                    else
                        break
                    end
                end

                k = 1

                while (i+k) < (n+1)
                    if y[i+k] > u₂
                        k += 1
                    else
                        break
                    end
                end

            ind = i-(j-1) : i+(k-1)

            clusterEnd = ind[end]

            c = Cluster(u₁, u₂, collect(ind), y[ind])

            push!(cluster, c)

            end

    end

    return cluster

end

"""
    getcluster(y::Vector{<:Real}, u::Real; runlength::Int=1)::Vector{Cluster}

Extract the clusters from vector `y`.

Threshold exceedances separated by fewer than *r* non-exceedances belong to the
same cluster. The value *r* is corresponds to the runlength parameter. This
approach is referred to as the *runs declustering scheme* (see Coles, 2001 sec. 5.3.2).

See also [`Cluster`](@ref).
"""
function getcluster(y::Vector{<:Real}, u::Real; runlength::Int=1)

    cluster = getcluster(y, u, u)

    if length(cluster)>1
        runscluster = Vector{Cluster}()
        cluster_current = cluster[1]

        for i=2:length(cluster)

            s = cluster[i].position[1] - cluster_current.position[end] - 1

            if s < runlength
                cluster_current = Extremes.merge(cluster_current, cluster[i])
            else
                push!(runscluster, cluster_current)
                cluster_current = cluster[i]
            end
        end
        push!(runscluster, cluster_current)

        return runscluster
    else
        return cluster
    end

end

"""
    length(c::Cluster)

Compute the cluster length.
"""
function length(c::Cluster)
    return length(c.position)
end

"""
    max(c::Cluster)

Compute the cluster maximum.
"""
function maximum(c::Cluster)
    return maximum(c.value)
end

"""
    sum(c::Cluster)

Compute the cluster sum.
"""
function sum(c::Cluster)
    return sum(c.value)
end

"""
    merge(c₁::Cluster, c₂::Cluster)

Merge cluster c₁ and c₂ into a single cluster.
"""
function merge(c₁::Cluster, c₂::Cluster)

    @assert c₁.u₁ ≈ c₂.u₁ "both clusters should have the same threshold to be merged."
    @assert c₁.u₂ ≈ c₂.u₂ "both clusters should have the same threshold to be merged."

    position = vcat(c₁.position, c₂.position)
    value = vcat(c₁.value, c₂.value)

    c = Cluster(c₁.u₁, c₁.u₂, position, value)

    return c

end

"""
    Base.show(io::IO, obj::Cluster)

Override of the show function for the objects of type EVA.

"""
function Base.show(io::IO, obj::Cluster)

    showCluster(io, obj)

end

"""
    showCluster(io::IO, obj::Cluster; prefix::String = " ")

Displays a Cluster with the prefix `prefix` before every line.

"""
function showCluster(io::IO, obj::Cluster; prefix::String = "")

    println(io, prefix, "Cluster")
    println(io, prefix, "u₁: ", obj.u₁)
    println(io, prefix, "u₂: ", obj.u₂)
    println(io, prefix, "position: ", obj.position)
    println(io, prefix, "value: ", obj.value)

end


text:
module PlasmoAlgorithms

using Plasmo
using JuMP
using Requires

import Plasmo.solve, Base.==

export Solution, lagrangesolve, bendersolve

include("lagrange.jl")
include("benders.jl")
include("solution.jl")
include("utils.jl")

end


text:
using DataFrames

function df2dic(df::DataFrame)
  ncolumn = ncol(df)
  colnames = names(df)
  key = Vector{String}(undef, 0)
  val = Vector(undef, 0)
  for i=1:ncolumn
  push!(key, string(names(evtdf)[i]))
  push!(val,evtdf[i])
  end
  dic=Dict(zip(key,val))
  return dic
  end

max_stars_repo_name: gulabd/SXTMerger

max_issues_repo_name: gulabd/SXTMerger


text:
# martindb contains price over time for household items in multiple stores.
# Plot the evolution of prices over time for common items (look for inflation).
using LibPQ, DataFrames, Plots, Dates, StatsPlots, StatsBase, SQLStrings

# utils
function check(result)
    @assert status(result) == LibPQ.libpq_c.PGRES_TUPLES_OK && isempty(LibPQ.error_message(result))  LibPQ.error_message(result)
end

function runquery(conn, sql::SQLStrings.Sql)
    query, args = SQLStrings.prepare(sql)
    LibPQ.execute(conn, query, args)
end

# connect to pg, no password, run pg with POSTGRES_HOST_AUTH_METHOD=trust
conn = LibPQ.Connection("postgresql://postgres@localhost:5433")

# list tables
result = execute(conn, """
SELECT *
FROM pg_catalog.pg_tables
WHERE schemaname != 'pg_catalog' AND
    schemaname != 'information_schema';
""")
check(result)
df = result |> DataFrame
show(df, allrows=true)

# load some tables
result = execute(conn, """SELECT * FROM vendor """)
check(result)
df_vendor = result |> DataFrame
show(df_vendor)

result = execute(conn, """SELECT * FROM product """)
check(result)
df_product = result |> DataFrame
show(df_product)

result = execute(conn, """SELECT * FROM label """)
check(result)
df_label = result |> DataFrame
show(df_label)

result = execute(conn, """SELECT * FROM price """)
check(result)
df_price = result |> DataFrame
show(df_price)

# some fields are NULL in SQL, missing in Julia
dropmissing!(df_price, :product_id)
dropmissing!(df_price, :vendor_id)

# find most common products (items)
cm_p = countmap(df_price.product_id)
scm_p = sort(collect(cm_p), by = x -> x[2], rev=true)
top_products = scm_p[1:10]  # top N

# find most common vendors (stores)
cm_v = countmap(df_price.vendor_id)
scm_v = sort(collect(cm_v), by = x -> x[2], rev=true)
top_vendors = scm_v[1:10]  # top N
top_vendor_ids = first.(top_vendors)

# make one plot per product, each containing multiple series (one for each top vendor)
for product_id_pair in top_products
    product_id = product_id_pair[1]
    df = filter(:id => ==(product_id), df_product)
    product_name = df[1, :name]

    # get price timeseries for this product, for all top vendors
    #   ignore promotions
    result = runquery(conn, sql```
    SELECT update_time, amount, vendor_id
    FROM price
    WHERE product_id = $product_id
    AND promotion IS NULL
    AND vendor_id IN ($(top_vendor_ids...))
    ORDER BY update_time ASC;
    ```)
    check(result)
    df = result |> DataFrame
    show(df)

    # parse timestamps
    dropmissing!(df)
    transform!(df, :update_time .=> ByRow(x -> x[3:21]); renamecols = false)
    transform!(df, :update_time .=> ByRow(x -> DateTime(x, dateformat"y-m-d H:M:S")); renamecols = false)
    df.amount = Float32.(df.amount)

    # pivot table into timeseries for each top vendors
    df_u = unstack(df, :update_time, :vendor_id, :amount; allowduplicates=true)

    # plot price timeseries for each vendor
    y_col_names = names(df_u, Not(:update_time))
    p = nothing
    for y_col_name in y_col_names
        vendor_name = (df_vendor.name[df_vendor.id .== y_col_name])[1]
        y = df_u[:, y_col_name]
        # since not all vendors have price at the same timestamp, pivot table contains a lot of missing data
        keeps = map(!ismissing, y)  # keep only not missing x,y pairs
        if y_col_name == y_col_names[1]
            p = plot(df_u.update_time[keeps], y[keeps], title = product_name, label = vendor_name, legend=:bottomright)
        else
            plot!(p, df_u.update_time[keeps], y[keeps], label = vendor_name)
        end
    end
    display(p)
end

max_stars_repo_name: cmey/martindb

max_issues_repo_name: cmey/martindb

max_forks_repo_name: cmey/martindb


text:
# based on the irc part of DonHo's bot
# https://github.com/DonHonerbrink/bruhbot

function irc_connect(tcp_sock::TCPSocket, config)
    tcp_create_sock(tcp_sock)
    tcp_connect(tcp_sock, config.hostname, config.port)
    return Status(tcp_sock.status)
end

function irc_send(tcp_sock::TCPSocket, buffer::String)
    buffer = buffer * '\r' * '\n'
    # @printf(stdout, "< %s", buffer)
    tcp_send(tcp_sock, buffer)
end

function irc_send_vec(tcp_sock::TCPSocket, chn::String, buffer::Vector{String})
    irc_send(tcp_sock, chn, mapreduce(x -> x * ',', *, buffer)[1:end-1])
end

# function irc_send(tcp_sock::TCPSocket, chn::String, buffer...)

# end

function irc_send(tcp_sock::TCPSocket, chn::String, buffer::String)
    start_buffer = @sprintf("PRIVMSG #%s :", chn)
    buffer = start_buffer * buffer * '\r' * '\n'
    @printf(stdout, "< %s", buffer)
    tcp_send(tcp_sock, buffer)
end

function read_oauth_file(filename::String)
    oauth = ""
    open(filename, "r") do file
        line = readline(file)
        oauth = line
    end
    return oauth
end

function irc_auth(tcp_sock::TCPSocket, nick::String, oauth::String)
    buffer = ""
    buffer = @sprintf("PASS %s\r\n", oauth)
    irc_send(tcp_sock, buffer)

    buffer = @sprintf("NICK %s\r\n", nick)
    irc_send(tcp_sock, buffer)

end

function irc_join(tcp_sock::TCPSocket, channel::String)
    buffer = ""
    buffer = @sprintf("JOIN #%s\r\n", channel)
    irc_send(tcp_sock, buffer)
end

function irc_readlines(tcp_sock::TCPSocket, config::Config)
    load_cmds()
    buffer = ""
    begin
        while !eof(tcp_sock)
            line = readline(tcp_sock)
            println(stdout,"> ", line)
            if line != nothing
                irc_parse_msg(tcp_sock, line, config)
            end
        end
    end

    return Status(tcp_sock.status), buffer
end

function irc_parse_msg(tcp_sock::TCPSocket, line::String, config::Config)
    if line == "PING :tmi.twitch.tv"
        irc_send(tcp_sock, "PONG :tmi.twitch.tv")
    end
    m = match(r":(?<sender>.*)!.*#(?<channel>\w+) :(?<msg>.*)", line)
    if m !== nothing
        sender = String(m[:sender])
        channel = String(m[:channel])
        msg = String(m[:msg])

        process_commands(tcp_sock, channel, msg, sender=sender,
                         preffix=config.cmd_preffix)
        @async log_msg(channel, sender, msg)
    end
end

function process_commands(tcp_sock::TCPSocket, chn::String, msg::String;
                          sender::String="", preffix::String="")
    cmd_regex = Regex("^" * preffix * "(?<cmd>\\w+) ?(?<body>.*)")
    command = match(cmd_regex, msg)
    if command != nothing
        if command[:cmd] == "ping"
            irc_send(tcp_sock, chn, "PONG")
        elseif command[:cmd] == "pog"
            irc_send(tcp_sock, chn, "@$sender Pogey")
        elseif command[:cmd] == "markov"
            irc_send(tcp_sock, chn, markov())
        elseif command[:cmd] == "weather"
            city = String(command[:body])
            if !isempty(city)
                text = read(`curl -4 -s https://wttr.in/$city\?format=4`, String)
                irc_send(tcp_sock, chn, text)
            end
        elseif command[:cmd] == "addcmd"
            defineCMD(tcp_sock, chn, String(command[:body]))
        elseif command[:cmd] == "commands"
            cmd_names = collect(keys(defined_cmds))
            if !isempty(cmd_names)
                #TODO(#5): find a way to print commands
                irc_send(tcp_sock, chn, "Defined commands: <insert cmds names here>")
            else
                irc_send(tcp_sock, chn, "No commands defined.")
            end
        elseif command[:cmd] in keys(defined_cmds)
            index = command[:cmd]
            defined_cmds[index][1](tcp_sock, chn, defined_cmds[index][2])
        end
    end

end

function log_msg(chn::String, sender::String, msg::String)
    msg = replace(msg, "\""=>"")
    filename = "twitch_log.db"
    db = SQLite.DB()
    db = DBInterface.connect(SQLite.DB, filename)
    execute_string = @sprintf "CREATE TABLE IF NOT EXISTS %s (
                             sender TEXT,
                             msg TEXT)" chn
    DBInterface.execute(db, execute_string)
    prepare_string = @sprintf "INSERT INTO %s VALUES(?,?)" chn
    q = DBInterface.prepare(db, prepare_string)
    SQLite.execute(q, (sender,msg))
    DBInterface.close!(db)

end

function markov()
    logfile::String = "twitch_log.db"
    buffer = ""
    db = SQLite.DB(logfile)
    cols = DBInterface.execute(db,"""SELECT * FROM john_pft
                                    WHERE msg NOT LIKE '!%' """
                               ) |> columntable
    foreach(x-> buffer *= x * " " , cols[2])
    gen_text = generate_markov_from_string(buffer)
    return gen_text
end

const cmd = Dict("say"=> irc_send, "test"=> println)

const defined_cmds = Dict{String, Tuple{Function, String}}()

# command functionality
function defineCMD(tcp_sock::TCPSocket, chn::String, expression::String)
    m = match(r"%(?<cmdName>\w+) %(?<func>\w+)*\((?<body>.*)\)", expression)
    # println("[DBG: ]", m)
    if m != nothing && !(m[:cmdName] in keys(cmd))
        defined_cmds[m[:cmdName]] = (cmd[m[:func]], String(m[:body]))
        irc_send(tcp_sock, chn, "command $(m[:cmdName]) added!")
        open("commands_test.bin", "w") do f
            serialize(f, defined_cmds)
        end
    end

end

function generate()
    for (key, command) in cmd
        eval(quote
             $(Symbol(key))(sock, chn::String) = $command(sock, chn, "hello")
             end)
    end
end

function load_cmds()
    #TODO(#6): check if files exists
    cmds_dump::String = "commands_test.bin"
    if isfile(cmds_dump)
        merge!(defined_cmds, deserialize(cmds_dump))
    end
end

max_stars_repo_name: Iaggelis/bald-bot

max_issues_repo_name: Iaggelis/bald-bot

max_forks_repo_name: Iaggelis/bald-bot


text:
function capability(dev::Int)
  major, minor = Cint[0], Cint[0]
  cuDeviceComputeCapability(major, minor, dev)
  Int(major[1]), Int(minor[1])
end

function ndevices()
  p = Cint[0]
  cuDeviceGetCount(p)
  Int(p[1])
end

function totalmem(dev::Int)
  bytes = Csize_t[0]
  cuDeviceTotalMem(bytes, dev)
  Int(bytes[1])
end

function attribute(attrib::Int, dev::Int)
  p = Cint[0]
  cuDeviceGetAttribute(p, attrib, dev)
  Int(p[1])
end

function attributes(dev::Int)
  "MAX_THREADS_PER_BLOCK" => attribute(1, dev),
  "MAX_BLOCK_DIM_X" => attribute(2, dev),
  "MAX_BLOCK_DIM_Y" => attribute(3, dev),
  "MAX_BLOCK_DIM_Z" => attribute(4, dev),
  "MAX_GRID_DIM_X" => attribute(5, dev),
  "MAX_GRID_DIM_Y" => attribute(6, dev),
  "MAX_GRID_DIM_Z" => attribute(7, dev),
  "MAX_SHARED_MEMORY_PER_BLOCK" => attribute(8, dev),
  "TOTAL_CONSTANT_MEMORY" => attribute(9, dev),
  "WARP_SIZE" => attribute(10, dev),
  "MAX_PITCH" => attribute(11, dev),
  "MAX_REGISTERS_PER_BLOCK" => attribute(12, dev)
end

function properties(dev::Int)
  p = Array(CUdevprop, 1)
  cuDeviceGetProperties(p, dev)
  p[1]
end

function Base.show(io::IO, p::CUdevprop)
  names = fieldnames(CUdevprop)
  for i = 1:nfields(CUdevprop)
    name = string(names[i])
    f = getfield(p, i)
    println(io, "$(name): $(f)")
  end
end


text:
# version of library to download
const version = v"2.00"

using BinDeps
using Libdl
@BinDeps.setup

function compatible_version(lib, handle)
   major, minor, rev = Ref{Cint}(), Ref{Cint}(), Ref{Cint}()
   f = Libdl.dlsym(handle, :mj_version)
   f == C_NULL && return false
   v = ccall(f, Int32, ())
   return v >= 200
end

baseurl = "https://www.roboti.us/download/mujoco200_"
basedir = dirname(@__FILE__)
unpack = joinpath(basedir, "mujoco200")
libpath = unpack*"/bin"

# library source code
if Sys.islinux()
   push!(BinDeps.defaults, Binaries)

   # First find three library dependents
   mujoco_glfw= library_dependency("libglfw", aliases=["libglfw.so.3"])
   mujoco_glew= library_dependency("libglew", aliases=["libglew"])
   mujoco_GL  = library_dependency("libGL") # looks in system
   mujoco_nix = library_dependency("libmujoco", aliases=["libmujoco200.so", "libmujoco200"])

   url = baseurl*"linux.zip"
   if isdir(unpack) == false
      @info("Downloading: ", url, " to ", unpack)
      file = Base.download(url) # to /tmp
      run(`unzip -o $file -d $basedir`)
      if isdir(unpack*"_linux/")
         run(`mv $(unpack*"_linux/") $(unpack)`)
      end
   end

   preloads = string("Libdl.dlopen(\"$(libpath)/libglew.so\", Libdl.RTLD_LAZY | Libdl.RTLD_DEEPBIND | Libdl.RTLD_GLOBAL)")

   provides(Binaries, URI(url), mujoco_glfw, unpacked_dir=unpack, installed_libpath=libpath)
   provides(Binaries, URI(url), mujoco_glew, unpacked_dir=unpack, installed_libpath=libpath)
   eval(Meta.parse(preloads))
   provides(Binaries, URI(url), mujoco_nix, unpacked_dir=unpack, installed_libpath=libpath, preload=preloads)

   @BinDeps.install Dict([(:libglfw, :libglfw),
                          (:libglew, :libglew),
                          (:libGL, :libGL),
                          (:libmujoco, :libmujoco)])
elseif Sys.is_apple()
   mujoco_osx = library_dependency("libmujoco", aliases=["libmujoco200"], validate=compatible_version)
   url = baseurl*"osx.zip"
   @info("Downloading: ", url, " to ", unpack)
   provides(Binaries, URI(url), mujoco_osx, unpacked_dir=unpack, installed_libpath=libpath)
   @BinDeps.install Dict(:libmujoco=>:libmujoco)
elseif Sys.is_windows()
   mujoco_win = library_dependency("libmujoco", aliases=["mujoco200"], validate=compatible_version)
   url = baseurl*"win$(Sys.WORD_SIZE).zip"
   @info("Downloading: ", url, " to ", unpack)
   provides(Binaries, URI(url), mujoco_win, unpacked_dir=unpack, installed_libpath=libpath)
   @BinDeps.install Dict(:libmujoco=>:libmujoco)
end

Sys.islinux() && pop!(BinDeps.defaults)


text:
@testset "simplify" begin

    @test simplify(:(10 - 5)) == 5
    @test simplify(:(u - 2)) == :(u - 2)
    @test simplify(:(1 * (u - 2))) == :(u - 2)
    @test simplify(:(1.0 * cos(x1))) == :(cos(x1))
    @test simplify(:(2 * 3x)) == :(6x)
    @test simplify(:(x ^ 0 / 2)) == 1/2

end


text:
using ..Tagging, ..IDS, ..Traits

export Member
# export ~, ciid, Member

# # Conditional Independence
# It is useful to create independent and conditionally independent random variables
# This has meaning for both random and free variables

"The `id`th member of the family `f`"
struct Member{F, ID}
  id::ID
  class::F
end

Base.:(==)(m1::Member, m2::Member) =
  m1.id == m2.id && m1.class == m2.class

Base.hash(x::Member) = hash(x.id)

# @inline (x::Member)(ω) = x.f(appendscope(ω, x.id))
@inline Var.recurse(x::Member, ω) = x.class(x.id, ω)

Base.show(io::IO, x::Member) = print(io, x.id,"@",x.class)

"""
Conditionally independent copy of `f`

if `g = ciid(f, id)` then `g` will be identically distributed with `f`
but conditionally independent given parents.
"""
@inline ciid(f, id) = Member(id, f)
@inline ciid(f, id::Integer, τ::Type{T} = defID()) where T =
  ciid(f, singletonid(T, id))

"`id ~ f` is an alias for `ciid(f, i)`"
@inline Base.:~(id, f) = ciid(f, id)


text:
#usage
#varinfo(r"oligo").content[1].rows[2:end][1][1]

#Dehann Fourie, Massachusetts Institute of Technology, Spring 2020

function varinfo_dict(rgx::Regex, dict::Dict=Dict{String, Any}())
  # get Markdown tables of variables matching expression
  vartables = varinfo(rgx).content[1].rows[2:end]
  # extract variable names as strings
  varnames = map(x->x[1], vartables)

  # combine names with values in a dictionary for JLD2/FileIO interface
  for v in varnames
    dict[v] = getfield(Main, Symbol(v))
  end

  return dict
end

#usage:
#varinfo_dict(r"time")

import FileIO: save

function save(filename::AbstractString, rgx::Regex)
  save(filename, varinfo_dict(rgx))
end

function save(filename::AbstractString, rgxs::Union{Vector{Regex}, NTuple{N, Regex}}) where N
  vardict = Dict{String, Any}()
  for rx in rgxs
    varinfo_dict(rx, vardict)
  end

  save(filename, vardict)
end

#usage:
#save(<file>, [r"PE",r"mu",r"light"])
#save(<file>, (r"PE",r"mu",r"light"))

max_stars_repo_name: hsosik/NES-LTER

max_issues_repo_name: hsosik/NES-LTER

max_forks_repo_name: hsosik/NES-LTER


text:
module FedeDist
using Distances: PreMetric

function simcarn_diff(diff, th, use_simcarn)
    if !use_simcarn
        return diff < th
    end
    diff = diff % 12
    if diff == 0
        return 0 < th
    elseif diff == 1
        # minor second
        return 0.8 < th
    elseif diff == 2
        # major second
        return 0.8 < th
    elseif diff == 3
        # minor third
        return 0.25 < th
    elseif diff == 4
        # major third
        return 0.25 < th
    elseif diff == 5
        # perfect fourth
        return 0.7 < th
    elseif diff == 6
        # diminished fifth
        return 0.5 < th
    elseif diff == 7
        # perfect fifth
        return 0.25 < th
    elseif diff == 8
        # minor sixth
        return 0.6 < th
    elseif diff == 9
        # major sixth
        return 0.6 < th
    elseif diff == 10
        # minor seventh
        return 0.5 < th
    elseif diff == 11
        # major seventh
        return 0.8 < th
    else
        return 1 < th
    end
end

"""
Counts how many elements in `x` and `y` are common; each element is counted at
most once, so that the maximum values returned are `length(x)` and `length(y)`
"""
function my_intersect_count(x, y, th, simcarn)

    count_x::Int64 = 0
    count_y::Int64 = 0
    last_x = -1
    free_y = trues(length(y))
    for (i, x_val) in enumerate(x)
        for (j, y_val) in enumerate(y)
            if simcarn_diff(abs(x_val - y_val), th, simcarn)
                if last_x < i
                    count_x += 1
                    last_x = i
                end
                if free_y[j]
                    count_y += 1
                    free_y[j] = false
                end
            end
        end
    end

    return count_x, count_y
end

"""
Returns the indices referred to `x` and `y` that match common elements
"""
function my_intersect_idx(x, y, th, simcarn)

    common_x = Int64[]
    common_y = Int64[]
    for (i, x_val) in enumerate(x), (j, y_val) in enumerate(y)
        if simcarn_diff(abs(x_val - y_val), th, simcarn)
            push!(common_x, i)
            push!(common_y, j)
        end
    end

    return common_x, common_y
end

"""
match pitches if their difference lies under `th`
"""
function _jaccard_dist(sample1::Vector{Int64}, sample2::Vector{Int64},
th::Float64,
                       simcarn::Bool)::Float64

    _intersect = my_intersect_count(sample1, sample2, th, simcarn)
    intersect = min(_intersect[1], _intersect[2])
    @fastmath return 1 - intersect / (length(sample1) + length(sample2) - intersect)
end

struct JaccardDist <: PreMetric
    th::Float64
    simcarn::Bool
end

function (self::JaccardDist)(x::Vector{Int64}, y::Vector{Int64})
    return _jaccard_dist(x, y, self.th, self.simcarn)
end
end # module


text:
abstract type AbstractIntegrator end

struct Leapfrog{T<:AbstractFloat} <: AbstractIntegrator
    ϵ   ::  T
end

# Create a `Leapfrog` with a new `ϵ`
function (::Leapfrog)(ϵ::AbstractFloat)
    return Leapfrog(ϵ)
end

function is_valid(v::AbstractVector{<:Real})
    if any(isnan, v) || any(isinf, v)
        return false
    end
    return true
end

function lf_momentum(ϵ::T, h::Hamiltonian, θ::AbstractVector{T}, r::AbstractVector{T}) where {T<:Real}
    _∂H∂θ = ∂H∂θ(h, θ)
    !is_valid(_∂H∂θ) && return r, false
    return r - ϵ * _∂H∂θ, true
end

function lf_position(ϵ::T, h::Hamiltonian, θ::AbstractVector{T}, r::AbstractVector{T}) where {T<:Real}
    return θ + ϵ * ∂H∂r(h, r)
end

function step(lf::Leapfrog{F}, h::Hamiltonian, θ::AbstractVector{T}, r::AbstractVector{T}) where {F<:AbstractFloat,T<:Real}
    r_new, _is_valid = lf_momentum(lf.ϵ / 2, h, θ, r)
    !_is_valid && return θ, r, false
    θ_new = lf_position(lf.ϵ, h, θ, r_new)
    r_new, _is_valid = lf_momentum(lf.ϵ / 2, h, θ_new, r_new)
    !_is_valid && return θ, r, false
    return θ_new, r_new, true
end

# TODO: double check the function below to see if it is type stable or not
function steps(lf::Leapfrog{F}, h::Hamiltonian, θ::AbstractVector{T}, r::AbstractVector{T}, n_steps::Int) where {F<:AbstractFloat,T<:Real}
    n_valid = 0
    r_new, _is_valid = lf_momentum(lf.ϵ / 2, h, θ, r)
    !_is_valid && return θ, r, n_valid
    r = r_new
    for i = 1:n_steps
        θ_new = lf_position(lf.ϵ, h, θ, r)
        r_new, _is_valid = lf_momentum(i == n_steps ? lf.ϵ / 2 : lf.ϵ, h, θ, r)
        if !_is_valid
            # The reverse function below is guarantee to be numerical safe.
            # This is because we know the previous step was valid.
            r, _ = lf_momentum(-lf.ϵ / 2, h, θ, r)
            return θ, r, n_valid
        end
        θ, r = θ_new, r_new
        n_valid = n_valid + 1
    end
    return θ, r, n_valid
end


text:
@testset "LongSubSeq" begin

@testset "Construction" begin
	seq = LongSequence{AminoAcidAlphabet}([AA_A, AA_V, AA_W, AA_Y, AA_H])
	v1 = LongSubSeq{AminoAcidAlphabet}(seq.data, 2:4)
	v2 = LongSubSeq(seq, 2:4)
	v3 = view(seq, 2:4)
	v4 = @view seq[2:4]
	v5 = LongSubSeq(seq)
	vv = LongSubSeq(v1, 2:3)
	vv2 = v1[2:3]
	vv3 = LongSubSeq(vv)

	@test_throws BoundsError LongSubSeq(seq, 0:4)
	@test_throws BoundsError LongSubSeq(seq, 1:6)
	@test_throws BoundsError LongSubSeq(v1, 1:4)

    @test collect(v5) == collect(seq)
	@test typeof(v1) == typeof(v2) == typeof(v3) == typeof(v4) == typeof(vv) == LongSubSeq{AminoAcidAlphabet}
	@test v1 == v2 == v3 == v4

	@test vv == vv2 == vv3
	vv[1] = AA_V
	@test vv == vv2 == vv3
end

@testset "Basics" begin
	seq = LongSequence{AminoAcidAlphabet}([AA_A, AA_V, AA_W, AA_Y, AA_H])
	v1 = LongSubSeq{AminoAcidAlphabet}(seq, 2:4)
	v2 = LongSubSeq(seq, 1:0)

	@test length(v1) == 3
	@test !isempty(v1)
	@test isempty(v2)
	@test length(v2) == 0

	v1[1] = 'N'
	v1[2] = 'K'
	@test String(seq) == "ANKYH"
end

@testset "Conversion" begin
	seq = LongDNASeq("TAGTATCGAAMYCGNA")
	v = LongSubSeq(seq, 3:14)

	@test LongSequence(v) == seq[3:14]
	s2 = LongSequence{RNAAlphabet{4}}(seq[3:14])
	@test LongSequence{RNAAlphabet{4}}(v) == s2

	@test LongSequence(LongSubSeq{RNAAlphabet{4}}(seq)) == LongSequence{RNAAlphabet{4}}(seq)
	@test LongSubSeq{RNAAlphabet{4}}(seq) == LongSequence{RNAAlphabet{4}}(seq)
end

@testset "Transformations" begin
	# Reverse!
	str = "SKVANNSFDGRKIQAWPSRQ"
	seq = LongAminoAcidSeq(str)
	seq2 = copy(seq)
	v = view(seq, 1:lastindex(seq))

	reverse!(v)
	@test seq == LongAminoAcidSeq(reverse(str))
	@test seq == v
	@test seq != seq2

	reverse!(v)
	@test seq == LongAminoAcidSeq(str)
	@test seq == v
	@test seq == seq2

	seq = LongDNASeq("TGAGTCGTAGGAAGGACCTAAA")
	seq2 = copy(seq)
	v = LongSubSeq(seq2, 3:15)
	complement!(v)
	@test seq2[3:15] == complement(seq[3:15])
	@test seq2[1:2] == dna"TG"
	@test seq2[16:end] == seq[16:end]
end

@testset "Copying" begin
	seq = LongRNASeq("UAUUAACCGGAGAUCAUUCAGGUAA")
	v1 = view(seq, 1:3)
	v2 = view(seq, 4:11)

	# Can't resize views
	@test_throws Exception copy!(v1, v2)

	# Works even when sharing underlying data
	# Note it is not possible to have v2 == v3 after copying
	v3 = view(seq, 1:8)
	before = LongSequence(v3)
	copy!(v2, v3)
	@test v2 == before

	# Also works with nonshared data
	v1 = view(randaaseq(20), 3:17)
	v2 = view(randaaseq(20), 3:17)
	copy!(v1, v2)
	@test v1 == v2
end

end # seqview


text:
using HarwellRutherfordBoeing

hb_matrices = ["lock1074.pse" "well1850.rra" "young3c.csa" "illc1033.rra" "mahindas.rua"]

for hb_matrix in hb_matrices
  M = HarwellBoeingMatrix(hb_matrix)
  show(STDOUT, M)
  print(M)
  @printf("\n")
end

rb_matrices = ["commanche_dual.rb"]

for rb_matrix in rb_matrices
  M = RutherfordBoeingData(rb_matrix)
  show(STDOUT, M)
  print(M)
  @printf("\n")
end

# Sample supplementary data files from the technical report.
rb_data = ["ordering.rb", "denserhs.rb", "sparserhs.rb", "estimate.rb", "solution.rb"]

for rb_datum in rb_data
  M = RutherfordBoeingData(rb_datum)
  show(STDOUT, M)
  print(M)
  @printf("\n")
end


text:
using ArgParse

include("./scenario_coverage.jl")
include("./throughput_guarantee.jl")
include("./availability.jl")
include("./cutoff_error.jl")
include("./path_selection.jl")
include("./probability_noise.jl")
include("./network_utilization.jl")
include("./throughput.jl")
include("./timer.jl")

function readInput(message, default, type)
    print(message)
    try
        if type == String
            res = readline()
            return length(res) > 0 ? res : default
        else
            return parse(type, readline())
        end
    catch
        return default
    end
end

function parse_commandline()
    s = ArgParseSettings()
    @add_arg_table! s begin
        "experiment"
            help = "Type of experiment to run. One of...
                            scenarios_coverage (Fig 12a)
                            optimizer_times (Fig 12c)
                            throughput_guarantee (Fig 10)
                            availability (Fig 7)
                            cutoff_error (Fig 12b)
                            path_selection (Fig 11)
                            probability_noise (Table 3)
                            throughput (Fig 9)
                            utilization"
        "--plot", "-p"
            help = "Boolean whether or not to plot the results of the given experiment"
            action = :store_true
    end

    return parse_args(s)
end

Base.@ccallable function julia_main()::String
    parsed_args = parse_commandline()

    plot = parsed_args["plot"]
    experiment = parsed_args["experiment"]
    # plot = true
    # experiment = "availability"
    print(experiment)
    if experiment == "scenario_coverage"
        shape = readInput("Weibull shape (0.8): ", 0.8, Float64)
        scale = readInput("Weibull scale (0.0001): ", 0.0001, Float64)
        topology = readInput("Topology (B4): ", "B4", String)
        cutoffs = map(i -> parse(Float64, i), split(readInput("Cutoffs (.001,.0001,.00001,.000001,.0000001): ", ".001,.0001,.00001,.000001,.0000001", String), ","))
        iterations = readInput("Iterations (100): ", 100, Int)
        scenarioCoverage("$topology", iterations, cutoffs; shape=shape, scale=scale, weibull=true, plot=plot)
    elseif experiment == "optimizer_times"
        topologies = split(readInput("Topologies (B4,IBM,XNet,ATT): ", "B4,IBM,XNet,ATT", String), ",")
        cutoffs = map(i -> parse(Float64, i), split(readInput("Cutoffs (.001,.0001,.00001,.000001): ", ".001,.0001,.00001,.000001", String), ","))
        iterations = readInput("Iterations (100): ", 100, Int)
        timeOptimizer(topologies, cutoffs, iterations, plot=plot)
    elseif experiment == "throughput_guarantee"
        topologies = split(readInput("Topologies (B4,IBM): ", "B4,IBM", String), ",")
        availabilities = map(i -> parse(Float64, i), split(readInput("Availabilities (.99, .999, .9999, .99995, .99999): ", ".99, .999, .9999, .99995, .99999", String), ","))
        cutoff = readInput("Cutoff (0.00000003): ", 0.00000003, Float64)
        num_demands = readInput("Number of demands (2): ", 2, Int)
        iterations = readInput("Iterations (2): ", 2, Int)
        getThroughputGuarantees(availabilities, cutoff, topologies, num_demands, iterations, plot=plot)
    elseif experiment == "availability"
        topologies = split(readInput("Topologies (IBM): ", "IBM", String), ",")
        algorithms = split(readInput("Algorithms (TEAVAR,SMORE,ECMP,FFC-1): ", "TEAVAR,SMORE,ECMP,FFC-1", String), ",")
        cutoff = readInput("Cutoff (0.0001): ", 0.0001, Float64)
        weibull_scale = readInput("Weibull scale (0.001): ", 0.001, Float64)
        num_demands = readInput("Number of demands (10): ", 10, Int)
        iterations = readInput("Iterations (10): ", 10, Int)
        demand_downscales = map(i -> parse(Float64, i), split(readInput("Demand downscales (2): ", "2", String), ","))
        start = readInput("Start (1): ", 1, Float64)
        step = readInput("Step (0.1): ", 0.1, Float64)
        finish = readInput("Finish (4.0): ", 4, Float64)
        # paths = readInput("Paths (SMORE): ", "SMORE", String)
        availabilityPlot(algorithms, topologies, demand_downscales, num_demands, iterations, cutoff, start, step, finish, weibull_scale=weibull_scale, paths="KSP", k=12, plot=plot)
    elseif experiment == "cutoff_error"
        topology = readInput("Topology (B4): ", "B4", String)
        cutoffs = map(i -> parse(Float64, i), split(readInput("Cutoffs (.0001,.00001,.000001,.0000001): ", ".0001,.00001,.000001,.0000001", String), ","))
        num_demands = readInput("Number of demands (10): ", 10, Int)
        iterations = readInput("Iterations (10): ", 10, Int)
        weibull_scale = readInput("Weibull scale (0.0001): ", 0.0001, Float64)
        # demand_downscale = readInput("Demand downscale (0.5): ", 0.5, Float64)
        topologyCutoffError(topology, num_demands, iterations, cutoffs, demand_downscale=1.0, weibull_scale=weibull_scale)
    elseif experiment == "path_selection"
        topologies = split(readInput("Topologies (B4,IBM): ", "B4,IBM", String), ",")
        demand_downscales = map(i -> parse(Float64, i), split(readInput("Demand downscales (4000,4000): ", "4000,4000", String), ","))
        availabilities = map(i -> parse(Float64, i), split(readInput("Availabilities (.9,.92,.94,.96,.98,.99): ", ".9,.92,.94,.96,.98,.99", String), ","))
        cutoff = readInput("Cutoff (0.001): ", 0.0001, Float64)
        num_demands = readInput("Number of demands (6): ", 6, Int)
        ksp = map(i -> parse(Int, i), split(readInput("KSP (4,6): ", "4,6", String), ","))
        paths = split(readInput("Paths (SMORE,FFC): ", "SMORE,FFC", String), ",")
        pathSelection(topologies, demand_downscales, paths, num_demands, availabilities, cutoff, ksp=ksp, plot=plot)
    elseif experiment == "probability_noise"
        topologies = split(readInput("Topologies (B4): ", "B4", String), ",")
        demand_downscales = map(i -> parse(Float64, i), split(readInput("Demand downscales (1): ", "1", String), ","))
        cutoff = readInput("Cutoff (0.00001): ", 0.00001, Float64)
        num_demands = readInput("Number of demands (2): ", 2, Int)
        iterations = readInput("Iterations (20): ", 20, Int)
        noises = map(i -> parse(Float64, i), split(readInput("Noises (.01,.05,.1,.15,.2): ", ".01,.05,.1,.15,.2", String), ","))
        probabilityNoise(topologies, demand_downscales, num_demands, iterations, cutoff, noises, paths="SMORE", weibull_scale=.001, add_noise="EVENTS", plot=plot)
    elseif experiment == "throughput"
        topologies = split(readInput("Topologies (B4,ATT): ", "B4,ATT", String), ",")
        demand_downscales = map(i -> parse(Float64, i), split(readInput("Demand downscales (1,1): ", "1,1", String), ","))
        algorithms = split(readInput("Algorithms (TEAVAR,SMORE,ECMP,FFC): ", "TEAVAR,SMORE,ECMP,FFC", String), ",")
        availabilities = map(i -> parse(Float64, i), split(readInput("Availabilities (.9,.95,.99,.999,.9999): ", ".9,.95,.99,.999,.9999", String), ","))
        cutoff = readInput("Cutoff (0.00001): ", 0.00001, Float64)
        num_demands = readInput("Number of demands (4): ", 4, Int)
        iterations = readInput("Iterations (4): ", 4, Int)
        num_paths = readInput("Num paths (4): ", 4, Int)
        getThroughputGraphs(algorithms, topologies, demand_downscales, num_demands, iterations, availabilities, cutoff, num_paths, teavar_paths="KSP", weibull_scale=.0001, plot=plot)
    elseif experiment == "utilization"
        topology = readInput("Topology (B4): ", "B4", String)
        availabilities = map(i -> parse(Float64, i), split(readInput("Availabilities (.99,.999,.9999): ", ".99,.999,.9999", String), ","))
        cutoff = readInput("Cutoff (0.00001): ", 0.00001, Float64)
        num_demands = readInput("Number of demands (3): ", 3, Int)
        iterations = readInput("Iterations (3): ", 3, Int)
        network_utilization(topology, 1, 1, num_demands, iterations, cutoff, availabilities, plot=plot)
    end
    return "...Complete"
end

julia_main()


text:
using RDatasets, DataFrames, Random, Statistics, LinearAlgebra
using MultivariateStats, LaTeXStrings, Plots; pyplot()
Random.seed!(0)

df = dataset("MASS", "cpus")
n = size(df)[1]
df = df[shuffle(1:n),:]

K = 10
nG = Int(floor(n/K))
n = K*nG
println("Loosing $(size(df)[1] - n) observations.")

lamGrid = 0:100:30000

devSet(k) = collect(1+nG*(k-1):nG*k)
trainSet(k) = setdiff(1:n,devSet(k))

xTrain(k) = convert(Array{Float64,2},df[trainSet(k),[:Cach, :ChMin]])
xDev(k) = convert(Array{Float64,2},df[devSet(k),[ :Cach, :ChMin]])

yTrain(k) = convert(Array{Float64,1},df[trainSet(k),:Perf])
yDev(k) = convert(Array{Float64,1},df[devSet(k),:Perf])

errVals = zeros(length(lamGrid))
for (i,lam) in enumerate(lamGrid)
    errSamples = zeros(K)
    for k in 1:K
        beta = ridge(xTrain(k),yTrain(k),lam)
        errSamples[k] = norm([ones(nG) xDev(k)]*beta - yDev(k) )^2
    end
    errVals[i] = sqrt(mean(errSamples))
end

i = argmin(errVals)
bestLambda = lamGrid[i]

betaFinal = ridge(convert(Array{Float64,2},df[:,[:Cach, :ChMin]]),
                  convert(Array{Float64,1},df[:,:Perf]),bestLambda)

macro RR(x) return:(round.($x,digits = 3)) end
println("Found best lambda for regularization: ", bestLambda)
println("Beta estimate: ", @RR betaFinal)

plot(lamGrid, errVals,legend = false,
     xlabel = L"\lambda", ylabel = "Loss")
plot!([bestLambda,bestLambda],[0,10^3], c = :black, ylim = (750, 1250))

max_stars_repo_name: Yoshinobu-Ishizaki/StatsWithJuliaBook

max_issues_repo_name: Yoshinobu-Ishizaki/StatsWithJuliaBook

max_forks_repo_name: Yoshinobu-Ishizaki/StatsWithJuliaBook


text:
endian(::Type{C}) where {T, fr, fg, fb, en, C <: AbstractStorageRGB{T, fr, fg, fb, en}} = en
nbitsfr(::Type{C}) where {T, fr, fg, fb, C <: AbstractStorageRGB{T, fr, fg, fb}} = fr
nbitsfg(::Type{C}) where {T, fr, fg, fb, C <: AbstractStorageRGB{T, fr, fg, fb}} = fg
nbitsfb(::Type{C}) where {T, fr, fg, fb, C <: AbstractStorageRGB{T, fr, fg, fb}} = fb
nshiftr(::Type{C}) where {C} = nbitsfg(C) + nshiftg(C)
nshiftg(::Type{C}) where {C} = nbitsfb(C) + nshiftb(C)
nshiftb(::Type{C}) where {T, fr, fg, fb, C <: AbstractStorageRGB{T, fr, fg, fb}} = 0
nshiftb(::Type{C}) where {C <: Union{RGBX444LE, RGBX444BE}} = 4
rawtype(::Type{C}) where {C <: AbstractStorageRGB} =
    sizeof(C) == 1 ? UInt8 : sizeof(C) == 2 ? UInt16 : UInt32
saturatedr(::Type{C}) where {C <: AbstractStorageRGB} = ~(typemax(rawtype(C)) << nbitsfr(C))
saturatedg(::Type{C}) where {C <: AbstractStorageRGB} = ~(typemax(rawtype(C)) << nbitsfg(C))
saturatedb(::Type{C}) where {C <: AbstractStorageRGB} = ~(typemax(rawtype(C)) << nbitsfb(C))
maskr(::Type{C}) where {C <: AbstractStorageRGB} = saturatedr(C) << nshiftr(C)
maskg(::Type{C}) where {C <: AbstractStorageRGB} = saturatedg(C) << nshiftg(C)
maskb(::Type{C}) where {C <: AbstractStorageRGB} = saturatedb(C) << nshiftb(C)

endian(::C) where {C <: AbstractStorageRGB} = endian(C)
nbitsfr(::C) where {C <: AbstractStorageRGB} = nbitsfr(C)
nbitsfg(::C) where {C <: AbstractStorageRGB} = nbitsfg(C)
nbitsfb(::C) where {C <: AbstractStorageRGB} = nbitsfb(C)
nshiftr(::C) where {C <: AbstractStorageRGB} = nshiftr(C)
nshiftg(::C) where {C <: AbstractStorageRGB} = nshiftg(C)
nshiftb(::C) where {C <: AbstractStorageRGB} = nshiftb(C)
saturatedr(::C) where {C <: AbstractStorageRGB} = saturatedr(C)
saturatedg(::C) where {C <: AbstractStorageRGB} = saturatedg(C)
saturatedb(::C) where {C <: AbstractStorageRGB} = saturatedb(C)
maskr(::C) where {C <: AbstractStorageRGB} = maskr(C)
maskg(::C) where {C <: AbstractStorageRGB} = maskg(C)
maskb(::C) where {C <: AbstractStorageRGB} = maskb(C)

toh(c::C) where {C <: AbstractStorageRGB} = (endian(C) === :be ? ntoh : ltoh)(c.color)

# Accessors
red(c::Union{RGB565LE, RGB565BE, RGB555LE, RGB555BE}) =
    n3f5ton0f8((toh(c) >> nshiftr(c)) & saturatedr(c))
red(c::Union{XRGB444LE, XRGB444BE, RGBX444LE, RGBX444BE}) =
    n4f4ton0f8((toh(c) >> nshiftr(c)) & saturatedr(c))

green(c::Union{RGB565LE, RGB565BE}) = n2f6ton0f8((toh(c) >> nshiftg(c)) & saturatedg(c))
green(c::Union{RGB555LE, RGB555BE}) = n3f5ton0f8((toh(c) >> nshiftg(c)) & saturatedg(c))
green(c::Union{XRGB444LE, XRGB444BE, RGBX444LE, RGBX444BE}) =
    n4f4ton0f8((toh(c) >> nshiftg(c)) & saturatedg(c))

blue(c::Union{RGB565LE, RGB565BE, RGB555LE, RGB555BE}) =
    n3f5ton0f8((toh(c) >> nshiftb(c)) & saturatedb(c))
blue(c::Union{XRGB444LE, XRGB444BE, RGBX444LE, RGBX444BE}) =
    n4f4ton0f8((toh(c) >> nshiftb(c)) & saturatedb(c))

chroma(c::Union{Lab24, Luv24}) = sqrt(comp2(c)^2 + comp3(c)^2)

hue(c::Union{HSV24, HSL24, HLS24, HLS}) = comp1(c)
hue(c::Union{Lab24, Luv24}) = (h = atand(comp3(c), comp2(c)); h < 0 ? h + 360 : h)

comp1(c::Union{HSV24, HSL24, HLS24}) = getfield(c, :h_raw) * 2.0f0
comp1(c::Union{Lab24, Luv24}) = getfield(c, :l_raw) * 65537f0 * Float32(0x1919p-30)
comp2(c::Union{HSV24, HSL24, HLS24}) = @inbounds n0f8tof32[getfield(c, :s_raw) + 1]
comp2(c::Union{Lab24}) = getfield(c, :a_raw) - 128f0
comp2(c::Union{Luv24}) = getfield(c, :u_raw) * (354f0 / 255f0) - 134f0
comp2(c::HLS) = c.s
comp3(c::Union{HSV24}) = @inbounds n0f8tof32[getfield(c, :v_raw) + 1]
comp3(c::Union{HSL24, HLS24}) = @inbounds n0f8tof32[getfield(c, :l_raw) + 1]
comp3(c::Union{Lab24}) = getfield(c, :b_raw) - 128f0
comp3(c::Union{Luv24}) = getfield(c, :v_raw) * (262f0 / 255f0) - 140f0
comp3(c::HLS) = c.l

function Base.getproperty(c::HSV24, sym::Symbol)
    sym === :h && return comp1(c)
    sym === :s && return comp2(c)
    sym === :v && return comp3(c)
    getfield(c, sym)
end

function Base.getproperty(c::HSL24, sym::Symbol)
    sym === :h && return comp1(c)
    sym === :s && return comp2(c)
    sym === :l && return comp3(c)
    getfield(c, sym)
end

function Base.getproperty(c::HLS24, sym::Symbol)
    sym === :h && return comp1(c)
    sym === :l && return comp2(c)
    sym === :s && return comp3(c)
    getfield(c, sym)
end

floattype(::Type{HSV24}) = HSV{Float32}
floattype(::Type{HSL24}) = HSL{Float32}
floattype(::Type{HLS24}) = HLS{Float32}


text:
#data type heirachy tree

#all tradeables have n and q
abstract tradeable
#  n::Integer
#  q::float64 #should range in [0:1]
#  selling_min::float64
#  selling_max::float64
#end

#function +(a::tradeable,b::tradeable)
#  return tradeable(a.n+b.n,(a.n*a.q+b.n*b.q)/(a.n+b.n))
#end

abstract building
#  x::Integer #(x,y) == top,left corner
#  y::Integer
#  dx::Integer
#  dy::Integer
#  owner::agent
#  is_open::bool
#  cash_flow::float64
#  level::Integer
#  workers_per_level::Integer #currently no distinction for social classes
#  curr_workers::Integer
#  city::city

type buy_state
  item::tradeable
  buying::bool
  max_stock::Integer
  min_quality::Integer
  max_price::float64
end

abstract buyer <: building
#  list<buy_settings>
#

type retail_control
  item::tradeable
  last_sold::Integer
  selling_price::float64
end

abstract retail <: buyer
#  ads_per_level::Integer
#  current_ads::Integer
#  list<retail_control>

abstract researchable <: building
abstract occupyable <: building
abstract headquarters <: buyer
abstract residential <: occupyable
abstract offices <: occupyable
abstract industrial <: buyer

max_stars_repo_name: JKSano/netgameproj

max_issues_repo_name: JKSano/netgameproj

max_forks_repo_name: JKSano/netgameproj


text:
using Optim

function vector2values!(dst, θ)
    offset = 1
    for m in dst
        copy!(m.data, θ[offset:offset+length(m)-1])
        offset += length(m)
    end
end

function grad2vector!(w, src)
    offset = 1
    for m in src
        copy!(view(w,offset:offset+length(m)-1), m.grad)
        # fill!(m.grad,0)
        offset += length(m)
    end
end

function lbfgs(optfun, m, x; testgradient::Bool = false, options = Optim.Options(g_tol = 1e-8,
                             iterations = 50000,
                             f_calls_limit = 10000,
                             store_trace = false,
                             show_trace = true))
    function f(θ, m, ps, x)
        vector2values!(ps, θ)
        optfun(m,x)
    end

    function g!(w, θ, m, ps, x)
        vector2values!(ps, θ)
        zerograds!(ps)
        fVal = optfun(m, x);
        Flux.back!(fVal)
        grad2vector!(w, ps)
        Flux.data(fVal)
    end

    #test the gradient:
    ps = params(m)
    θ = randn(sum(length.(ps)))
    if testgradient
        w = zeros(length(θ))
        g!(w, θ)
        δ = maximum(abs.(Flux.Tracker.ngradient(f,θ)[1] .- w))
        δ < 1e-6 && error("gradient test failed, difference ",δ)
    end

    mf = freeze(m)
    optimize(θ -> f(θ, mf, ps, x) , (w,θ) ->  g!(w, θ, m, ps, x), θ, LBFGS(), options)
end

max_stars_repo_name: pevnak/FluxExtensions

max_issues_repo_name: pevnak/FluxExtensions

max_forks_repo_name: pevnak/FluxExtensions


text:
"""
    mosaic(f::TF, layers::Vector{T}) where {TF <: Function, T <: SimpleSDMLayer}

Joins a series of _possibly_ overlapping `layers` by applying the function `f`
to the values that occupy the same cells. Note that the function `f`  should
return a single value and accept an vector as input. Functions like
`Statistics.mean`, etc, work well.

Using `mosaic` with `maximum` is equivalent to `raster::merge` from the *R*
package `raster`.
"""
function mosaic(f::TF, layers::Vector{T}) where {TF <: Function, T <: SimpleSDMLayer}

    # Check the dimensions
    for i in 1:(length(layers)-1)
        for j in 1:length(layers)
            if !(all(stride(layers[i]) .≈ stride(layers[j])))
                throw(DimensionMismatch("Layers $i and $j have different strides"))
            end
        end
    end

    # Check the types
    itypes = eltype.(layers)
    if length(unique(itypes)) > 1
        @warn """
        The numeric types of the layers are not unique, this can cause performance issues.
        The returned layer will have $(first(itypes)).
        """
    end

    # Get the new bounding boxes
    n_left = minimum([layer.left for layer in layers])
    n_right = maximum([layer.right for layer in layers])
    n_bottom = minimum([layer.bottom for layer in layers])
    n_top = maximum([layer.top for layer in layers])

    # Get the gridsize
    nr = round(Int64, (n_top - n_bottom)/2stride(layers[1],1))
    nc = round(Int64, (n_right - n_left)/2stride(layers[1],2))

    # Prepare the grid
    grid = fill(nothing, nc, nr)
    grid = convert(Matrix{Union{Nothing,itypes[1]}}, grid)
    L = SimpleSDMResponse(grid, n_left, n_right, n_bottom, n_top)

    # Fill in the information
    for lat in latitudes(L)
        for lon in longitudes(L)
            V = [layer[lon, lat] for layer in layers]
            filter!(!isnothing, V)
            filter!(!isnan, V)
            length(V) == 0 && continue
            L[lon, lat] = convert(itypes[1], f(V))
        end
    end

    # Return
    return T <: SimpleSDMResponse ? L : convert(SimpleSDMPredictor, L)
end


text:
@testset "Discretization" begin
  @testset "FanTriangulation" begin
    pts  = P2[(0.,0.), (1.,0.), (1.,1.), (0.75,1.5), (0.25,1.5), (0.,1.)]
    tris = [Triangle([pts[1], pts[i], pts[i+1]]) for i in 2:length(pts)-1]
    hex  = Hexagon(pts)
    mesh = discretize(hex, FanTriangulation())
    @test nvertices(mesh) == 6
    @test nelements(mesh) == 4
    @test eltype(mesh) <: Triangle
    @test vertices(mesh) == pts
    @test collect(elements(mesh)) == tris
  end

  @testset "RegularDiscretization" begin
    sphere = Sphere(P2(0,0), T(1))
    mesh = discretize(sphere, RegularDiscretization(10))
    @test nvertices(mesh) == 10
    @test nelements(mesh) == 10
    @test eltype(mesh) <: Segment
    @test nvertices.(mesh) ⊆ [2]

    sphere = Sphere(P3(0,0,0), T(1))
    mesh = discretize(sphere, RegularDiscretization(10))
    @test nvertices(mesh) == 10*10 + 2
    @test nelements(mesh) == (10)*(10-1) + 2*(10)
    @test eltype(mesh) <: Ngon
    @test nvertices.(mesh) ⊆ [3,4]

    ball = Ball(P2(0,0), T(1))
    mesh = discretize(ball, RegularDiscretization(10))
    @test nvertices(mesh) == 10*10 + 1
    @test nelements(mesh) == (10)*(10-1) + 10
    @test eltype(mesh) <: Ngon
    @test nvertices.(mesh) ⊆ [3,4]
  end

  @testset "Dehn1899" begin
    octa = Octagon(P2[(0.0,0.0), (0.5,-0.5), (1.0,0.0), (1.5,0.5),
                      (1.0,1.0), (0.5,1.5), (0.0,1.0), (-0.5,0.5)])
    mesh = discretize(octa, Dehn1899())
    @test nvertices(mesh) == 8
    @test nelements(mesh) == 6
    @test eltype(mesh) <: Triangle

    octa = Octagon(P3[(0.0,0.0,0.0), (0.5,-0.5,0.0), (1.0,0.0,0.0), (1.5,0.5,0.0),
                      (1.0,1.0,0.0), (0.5,1.5,0.0), (0.0,1.0,0.0), (-0.5,0.5,0.0)])
    mesh = discretize(octa, Dehn1899())
    @test nvertices(mesh) == 8
    @test nelements(mesh) == 6
    @test eltype(mesh) <: Triangle
  end

  @testset "FIST" begin
    𝒫 = Chain(P2[(0,0),(1,0),(1,1),(2,1),(2,2),(1,2),(0,0)])
    @test Meshes.ears(𝒫) == [2,4,5]

    𝒫 = Chain(P2[(0,0),(1,0),(1,1),(2,1),(1,2),(0,0)])
    @test Meshes.ears(𝒫) == [2,4]

    𝒫 = Chain(P2[(0,0),(1,0),(1,1),(1,2),(0,0)])
    @test Meshes.ears(𝒫) == [2,4]

    𝒫 = Chain(P2[(0,0),(1,1),(1,2),(0,0)])
    @test Meshes.ears(𝒫) == []

    𝒫 = Chain(P2[(0.443339268495331, 0.283757618605357),
                 (0.497822414616971, 0.398142813114205),
                 (0.770343126156527, 0.201815462842808),
                 (0.761236456732531, 0.330085709922366),
                 (0.985658085510286, 0.221530395507904),
                 (0.877899962498139, 0.325516131702896),
                 (0.561404274882782, 0.540334008885703),
                 (0.949459768187313, 0.396227653478068),
                 (0.594962560615951, 0.584927547374551),
                 (0.324208409133154, 0.607290684450708),
                 (0.424085089823892, 0.493532112641353),
                 (0.209843417261654, 0.590030658255966),
                 (0.27993878548962, 0.525162463476181),
                 (0.385557753911967, 0.322338556632868),
                 (0.443339268495331, 0.283757618605357)])
    @test Meshes.ears(𝒫) == [1,3,5,6,8,10,12,14]

    points = P2[(0,0),(1,0),(1,1),(2,1),(2,2),(1,2),(0,0)]
    connec = connect.([(4,5,6),(3,4,6),(3,6,1),(1,2,3)], Triangle)
    target = SimpleMesh(points[1:end-1], connec)
    poly = PolyArea(points)
    mesh = discretize(poly, FIST(shuffle=false))
    @test mesh == target
    @test Set(vertices(poly)) == Set(vertices(mesh))
    @test nelements(mesh) == length(vertices(mesh)) - 2
  end

  @testset "Miscellaneous" begin
    for method in [FIST(), Dehn1899()]
      triangle = Triangle(P2(0,0), P2(1,0), P2(0,1))
      mesh = discretize(triangle, method)
      @test vertices(mesh) == [P2(0,0), P2(1,0), P2(0,1)]
      @test collect(elements(mesh)) == [triangle]

      quadrangle = Quadrangle(P2(0,0), P2(1,0), P2(1,1), P2(0,1))
      mesh = discretize(quadrangle, method)
      elms = collect(elements(mesh))
      @test vertices(mesh) == [P2(0,0), P2(1,0), P2(1,1), P2(0,1)]
      @test eltype(elms) <: Triangle
      @test length(elms) == 2

      q = Quadrangle(P2(0,0), P2(1,0), P2(1,1), P2(0,1))
      t = Triangle(P2(1,0), P2(2,1), P2(1,1))
      m = Multi([q, t])
      mesh = discretize(m, method)
      elms = collect(elements(mesh))
      @test vertices(mesh) == [vertices(q); vertices(t)]
      @test vertices(elms[1]) ⊆ vertices(q)
      @test vertices(elms[2]) ⊆ vertices(q)
      @test vertices(elms[3]) ⊆ vertices(t)
      @test eltype(elms) <: Triangle
      @test length(elms) == 3

      outer = P2[(0,0),(1,0),(1,1),(0,1),(0,0)]
      hole1 = P2[(0.2,0.2),(0.4,0.2),(0.4,0.4),(0.2,0.4),(0.2,0.2)]
      hole2 = P2[(0.6,0.2),(0.8,0.2),(0.8,0.4),(0.6,0.4),(0.6,0.2)]
      poly  = PolyArea(outer, [hole1, hole2])
      chain, _ = bridge(poly, width=0.01)
      mesh  = discretizewithin(chain, method)
      @test nvertices(mesh) == 16
      @test nelements(mesh) == 14
      @test all(t -> area(t) > zero(T), mesh)

      # 3D chains
      chain = Chain(P3[(0,0,0), (1,0,0), (1,1,0), (0,1,1), (0,0,0)])
      mesh  = discretizewithin(chain, method)
      @test vertices(mesh) == vertices(chain)
      @test eltype(mesh) <: Triangle
      @test nelements(mesh) == 2
    end
  end

  @testset "Difficult examples" begin
    for method in [FIST(), Dehn1899()]
      poly = readpoly(T, joinpath(datadir, "taubin.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2

      poly = readpoly(T, joinpath(datadir, "poly1.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2

      poly = readpoly(T, joinpath(datadir, "poly2.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2

      poly = readpoly(T, joinpath(datadir, "poly3.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2

      poly = readpoly(T, joinpath(datadir, "poly4.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2

      poly = readpoly(T, joinpath(datadir, "poly5.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2

      poly = readpoly(T, joinpath(datadir, "smooth1.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2

      poly = readpoly(T, joinpath(datadir, "smooth2.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2

      poly = readpoly(T, joinpath(datadir, "smooth3.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2

      poly = readpoly(T, joinpath(datadir, "smooth4.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2

      poly = readpoly(T, joinpath(datadir, "smooth5.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2

      poly = readpoly(T, joinpath(datadir, "hole1.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == 32

      poly = readpoly(T, joinpath(datadir, "hole2.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == 30

      poly = readpoly(T, joinpath(datadir, "hole3.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == 32

      poly = readpoly(T, joinpath(datadir, "hole4.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == 30

      poly = readpoly(T, joinpath(datadir, "hole5.line"))
      mesh = discretize(poly, method)
      @test Set(vertices(poly)) == Set(vertices(mesh))
      @test nelements(mesh) == 32
    end
  end

  @testset "Triangulate" begin
    # triangulate is a helper function that calls an
    # appropriate discretization method depending on
    # the geometry type that is given to it
    box  = Box(P2(0,0), P2(1,1))
    ngon = Quadrangle(P2[(0,0),(1,0),(1,1),(0,1)])
    poly = readpoly(T, joinpath(datadir, "taubin.line"))
    for geom in [box, ngon, poly]
      mesh = triangulate(geom)
      @test Set(vertices(geom)) == Set(vertices(mesh))
      @test nelements(mesh) == length(vertices(mesh)) - 2
    end

    # triangulation of multi geometries
    box1  = Box(P2(0,0), P2(1,1))
    box2  = Box(P2(1,1), P2(2,2))
    multi = Multi([box1, box2])
    mesh  = triangulate(multi)
    @test nvertices(mesh) == 8
    @test nelements(mesh) == 4

    # triangulation of spheres
    sphere = Sphere(P3(0,0,0), T(1))
    mesh = triangulate(sphere)
    @test eltype(mesh) <: Triangle
    xs = coordinates.(vertices(mesh))
    @test all(x -> norm(x) ≈ T(1), xs)

    # triangulation of balls
    ball = Ball(P2(0,0), T(1))
    mesh = triangulate(ball)
    @test eltype(mesh) <: Triangle
    xs = coordinates.(vertices(mesh))
    @test all(x -> norm(x) ≤ T(1) + eps(T), xs)

    # triangulation of meshes
    grid = CartesianGrid{T}(3, 3)
    mesh = triangulate(grid)
    gpts = vertices(grid)
    mpts = vertices(mesh)
    @test nvertices(mesh) == 16
    @test nelements(mesh) == 18
    @test collect(mpts) == collect(gpts)
    @test eltype(mesh) <: Triangle
    @test measure(mesh) == measure(grid)

    if visualtests
      p1 = plot(grid, fillcolor=false)
      p2 = plot(mesh, fillcolor=false)
      p = plot(p1, p2, layout=(1,2), size=(600,300))
      @test_reference "data/triangulate-$T.png" p
    end
  end
end


text:
@recipe function f(block::Block{<:Real})
    seriestype --> :steppost
    return block.times, block.values
end


text:
using Genie.Router, JSON

Genie.config.run_as_server = true
Genie.config.cors_allowed_origins = ["*"]

route("/") do
  serve_static_file("welcome.html")
end

route("/service/status") do
  msg = Dict("status" => "OK", "code" => 200)
  JSON.json(msg)
end

route("/app/news/:secret/:userid") do

end

max_stars_repo_name: Kompendix/Klingelbeutel

max_issues_repo_name: Kompendix/Klingelbeutel

max_forks_repo_name: Kompendix/Klingelbeutel


text:
module OutputLSmod

type OutputLS
 stepmax::Float64
 step::Float64
 slope::Float64
 beta::Float64
 nbarmijo::Float64
 nbwolfe::Float64
end

#Initialisation
#function OutputLS()
# return OutputLS()
#end

#Mise à jour
#function Update(ols::OutputLS)
# return ols
#end

#Print
function Print(ols::OutputLS,n::Int64,verbose::Int64)
 if verbose>2
  println(" stepmax=",ols.stepmax," step=",ols.step," slope=",ols.slope," beta=",ols.beta," nbarmijo=",ols.nbarmijo," nbwolfe=",ols.nbwolfe)
 end

 return true
end

#end of module
end