text:
using ReTest, Pkg

Pkg.activate("ReTest")
Pkg.develop(PackageSpec(path="../InlineTest"))

module Trace
export trace
using ReTest: @test

const RUN = []

function trace(x)
    push!(RUN, x)
    @test true
end
end

function check(x...; runtests=false, verbose=true, stats=false, dry=false)
    args = x[1:end-1]
    expected = x[end]
    if expected isa AbstractString
        expected = split(x[end])
    end

    empty!(Trace.RUN)
    if runtests
        getfield(args[1], :runtests)(args[2:end]...; verbose=verbose, stats=stats, dry=dry)
    else
        retest(args...; verbose=verbose, stats=stats, dry=dry)
    end
    @test Trace.RUN == expected
end

macro chapter(title, x)
    title = string(title)

    if isempty(ARGS) || any(pat -> occursin(Regex(pat, "i"), title), ARGS)
        printstyled("\n\n", rpad("## $title #", 78, '#'), "\n\n", bold=true, color=:cyan)
        esc(x)
    end
end

# * M ........................................................................

module M
using ReTest

RUN = []

@testset "a" begin
    push!(RUN, "a")
    @test true
end

@testset "b$i" for i=1:2
    push!(RUN, "b$i")
    @test true
end

@testset verbose=true "c" begin
    push!(RUN, "c")
    @test true

    @testset "d" begin
        push!(RUN, "d")
        @test true
    end

    @testset "e$i" for i=1:2
        push!(RUN, "e$i")
        @test true
    end
end

@testset "f$i" verbose=true for i=1:1
    push!(RUN, "f$i")
    @test true

    @testset "g" begin
        push!(RUN, "g")
        @test true
    end

    @testset "h$i" for i=1:2
        push!(RUN, "h$i")
        @test true
    end
end

innertestsets = ["d", "e1", "e2", "g", "h1", "h2"]

function check(rx, list)
    empty!(RUN)
    retest(M, Regex(rx))
    @test RUN == list
    mktemp() do path, io
        redirect_stdout(io) do
            retest(M, Regex(rx), dry=true, id=false) # TODO: test with id=true
        end
        seekstart(io)
        expected = map(list) do t
            if t in innertestsets
                "  " * t
            else
                t
            end
        end
        expected = join(expected, '\n')
        actual = readchomp(io)
        if isempty(expected)
            @test startswith(actual, "No matching tests for module")
        else
            @test actual == expected
        end
    end
end
end #

@chapter M begin
    # we don't put these checks in a @testset, as this would modify filtering logic
    # (e.g. with `@testset "filtering" ...`, testset subjects would start with "/filtering/...")
    M.check("a", ["a"])
    M.check("a1", []) # testset is "final", so we do a full match
    M.check("b", ["b1", "b2"])
    M.check("/b", ["b1", "b2"])
    M.check("b1", ["b1"])
    M.check("c1", []) # "c1" is *not* partially matched against "/c/"
    M.check("c/1", []) # "c" is partially matched, but nothing fully matches afterwards
    M.check("c/d1", [])
    M.check("c/d", ["c", "d"])
    M.check("/c", ["c", "d", "e1", "e2"])
    M.check(".*d", ["c", "d"])
    M.check(".*(e1|e2)", ["c", "e1", "e2"])
    M.check("f1", ["f1", "g", "h1", "h2"])
    M.check("f",  ["f1", "g", "h1", "h2"])
    M.check(".*g", ["f1", "g"])
    M.check(".*h", ["f1", "h1", "h2"])
    M.check(".*h1", ["f1", "h1"])
    M.check(".*h\$", [])

    # by default, respect order of tests:
    M.check("", ["a", "b1", "b2", "c", "d", "e1", "e2", "f1", "g", "h1", "h2"])
    retest(M)
end

# * N ........................................................................

module N
using ReTest, ..Trace

# testing non-final non-toplevel testsets
@testset "i" begin
    trace("i")

    @testset "j" verbose=false begin # false, just to test that it works
        trace("j")

        @testset "k" begin
            trace("k")
        end
    end

    @testset "l$i" verbose=true for i=1:1
        trace("l$i")

        @testset "m" begin
            trace("m")
        end
    end
end
end # N

@chapter N begin
    check(N, r".*j1", ""; runtests=true)
    check(N, r".*j/1", ""; runtests=false)
    check(N, r"^/i/j0", ""; runtests=true)
    check(N, r"^/i/l10", ""; runtests=false)
end

# * P ........................................................................
# test ReTest's wrapping of non-regex patterns

module P
using ReTest, ..Trace

# testing non-final non-toplevel testsets
@testset "a" begin
    trace("a")

    @testset "b" begin
        trace("b")
    end

    @testset "b|c" begin
        trace("b|c")
    end
end

@testset "D&E" begin
    trace("D&E")
end
end # P

@chapter P begin
    check(P, "b", "a b b|c"; verbose=2) # an implicit prefix r".*" is added
    check(P, "B", "a b b|c"; verbose=0, runtests=true) # idem, case-insensitive
    check(P, r"B", "") # not case-insensitive

    if VERSION >= v"1.3"
        check(P, "b|c", "a b|c") # "b" is not matched
        check(P, "B|C", "a b|c") # idem, case-insensitive
    end

    check(P, "d&e", "D&E")
    check(P, "d&E", "D&E")
    check(P, r"d&E", "")
    check(P, r"d&E"i, "D&E")
end

# * multiple patterns ........................................................

module MultiPat
using ReTest, ..Trace

@testset "a" begin
    trace("a")

    @testset "b" begin
        trace("b")
    end
end

@testset "aa" begin
    trace("aa")
end

@testset "b" begin
    trace("c")
end

@testset "d$i" for i=1:2
    trace("d$i")
end

end # MultiPat

@chapter MultiPat begin
    check(MultiPat, "a", "a b aa")
    check(MultiPat, "b", "a b c")
    check(MultiPat, "a", "b", "a b")
    check(MultiPat, ("a", "b"), "a b")
    check(MultiPat, "b", r"a", "a b")
    check(MultiPat, "b", "d", "")
    check(MultiPat, "a", "e", "")
    check(MultiPat, ["aa", "2"], "aa d2")
    check(MultiPat, ["1", "2"], "d1 d2")
    check(MultiPat, ["aa", "2"], "d", "d2")
    check(MultiPat, ["aa", "2", ["2", "1"]], "d", "d1 d2")

    # with integers
    # check we don't collect the range:
    check(MultiPat, 1:Int64(10)^15, "a b aa c d1 d2")
    check(MultiPat, 5, "d1 d2")
    check(MultiPat, "a", 2:3, "a b aa")
    check(MultiPat, "a", 1:2, "a b")
    check(MultiPat, "a", [1, 3], "a aa")
    check(MultiPat, ["aa", 4], "aa c")

    # with Not
    check(MultiPat, not("a"), "c d1 d2")
    check(MultiPat, not(4:10), "a b aa")
    check(MultiPat, not((1:3, "b")), "a aa c d1 d2")
    check(MultiPat, not([1:2, "aa", not("d")]), "d1 d2")
    check(MultiPat, -2, -4, -5, -6, "a aa")
    check(MultiPat, (-3, "a"), "a b")
    check(MultiPat, -1:3, "a b aa c d1 d2") # TODO: test this were 2, 3 can be tested
                                            # without forcing also testing 1
end

# * StringPat ................................................................

module StringPat
using ReTest, ..Trace

@testset "aa" begin trace("aa") end
@testset "-a" begin trace("-a") end
@testset "b" begin trace("b") end

end # StringPat

@chapter StringPat begin
    check(StringPat, "a", "aa -a")
    check(StringPat, "-a", "b")
    check(StringPat, "--a", "-a")
    check(StringPat, not("--a"), "aa b")
    check(StringPat, "-aa", "-a b")
end

# * Module patterns ..........................................................

module ModPat
using ReTest, ..Trace

@testset "aa" begin
    trace("aa")
    @testset "b" begin
        trace("b")
    end
end

@testset "ab" begin
    trace("ab")
end

module In
module Ner
using ReTest, ....Trace

@testset "c" begin
    trace("c")
end
end end # In.Ner
end # ModPat

module ModPat2
using ReTest, ..Trace

@testset "ad" begin
    trace("ad")
end
end # ModPat2

@chapter ModPat begin
    check(ModPat, "aa b ab c")
    check(ModPat => 1:99, "aa b ab") # no recursive
    check(ModPat => "a", 1:2, "aa b")
    check(ModPat2 => "a", ModPat, 1:9, "ad aa b ab c") # ModPat recursive
    check(ModPat2 => ("a", 1:9), ModPat => 1:9, "ad aa b ab") # ModPat not recursive
    check(ModPat2 => "a", ModPat, 2:9, "aa b ab")
    check(ModPat2 => "a", ModPat, ModPat, 2:9, "aa b ab") # deduplicate
    check(ModPat2 => "", ModPat => "aa", 2, "aa b")
end

# * toplevel .................................................................

@chapter toplevel begin
    # The following test is just to exert `@assert allunique(TESTED_MODULES)` in
    # computemodules!, and must be run before any toplevel @testset in declared,
    # so that `Main` is not yet in TESTED_MODULES; we check that previous
    # tested modules, which are in submodules of Main, are not re-added to
    # TESTED_MODULES while going through submodules of Base.loaded_modules ∋ Main
    retest(dry=true)
    RUNTOP = []

    @testset "toplevel" begin
        # this tests that the testset is run exactly once
        # Main is special here, as it's both in Base.loaded_modules
        # and it gets registered automatically in ReTest.TESTED_MODULES
        push!(RUNTOP, "toplevel")
        @test true
    end

    retest(verbose=Inf)
    retest("a", shuffle=true, stats=true)
    retest(M, N, P, "b", dry=true)

    for v in (-rand(1:9), 4.2, -Inf)
        @test_throws ArgumentError retest(verbose=v)
    end

    @test RUNTOP == ["toplevel"]

    retest(r"^/f1", stats=true) # just test that a regex can be passed,
                                # and that stats works for multiple subtests
end

# * Overwritten ..............................................................

module Overwritten
using ReTest, ..Trace

@testset "first" begin
    trace(1)
end
end # Overwritten

@chapter Overwritten begin
    check(Overwritten, [1]; stats=true) # testing stats when there are not tests
end

module Overwritten
using ReTest, ..Trace

@testset "second" begin
    trace(2)
end
end

@chapter Overwritten begin
    check(Overwritten, [2])
    # 1 must not appear (i.e. ReTest must not keep a reference to
    # the old overwritten version of `Overwritten`
end

# * Loops ....................................................................

module Loops1
using ReTest, ..Trace

@testset "loops 1" begin
    trace(9)
    a = 1
    b = 2

    @testset "local$i" for i in (a, b)
        trace(i)
        @testset "sub" begin
            trace(0)

            @testset "final" begin
                trace(-1)
            end
        end
    end
end
end # Loops1

@chapter Loops begin
    # @test_logs (:warn, r"could not evaluate testset description.*") retest(Loops1, r"asd")
    # @test Loops1.RUN == [1, 0, 2, 0]
    # empty!(Loops1.RUN)
    # retest(Loops1) # should not log
    check(Loops1, [9, 1, 0, -1, 2, 0, -1])
    check(Loops1, 9:9, []) # when no regex is passed, even with the presence of statically
                           # unresolvable descriptions, we can filter out stuff
                           # (i.e. here, we don't run "loops 1" just in case "local$i" would
                           # be run, as we can determine from pattern 9:9 that nothing must run)
end

module Loops2
using ReTest, ..Trace

@testset "loops 2" begin
    @testset "generator $i $I" for (i, I) in (i => typeof(i) for i in (1, 2))
        trace(i)
        @testset "sub" begin
            trace(0)

            @testset "final" begin
                trace(-1)
            end
        end
    end
end
end # Loops2

# the test below has been solved
# TODO: check whether another run could lead to the same result, i.e. RUN == [1, 0, 2, 0] ?
# @test_logs (:warn, r"could not evaluate testset-for iterator.*") retest(Loops2, r"asd")
# @test Loops2.RUN == [1, 0, 2, 0]

@chapter Loops check(Loops2, [1, 0, -1, 2, 0, -1])

module Loops3
using ReTest, ..Trace

@testset "loops 3" begin
    @testset "generator $i $I" for (i, I) in [i => typeof(i) for i in (1, 2)]
        trace(i)
        @testset "sub" begin
            trace(0)

            @testset "final" begin
                trace(-1)
            end
        end
    end
end
end # Loops3

@chapter Loops begin
    check(Loops3, r"asd", [])
    check(Loops3, [1, 0, -1, 2, 0, -1])
end

module MultiLoops
using ReTest, ..Trace

C1, C2 = 1:2 # check that iteration has access to these values

@testset "multiloops $x $y $z" for (x, y) in zip(1:C2, 1:2), z in C1:x
    trace((x, z))
end
end # MultiLoops

@chapter Loops begin
    check(MultiLoops, [(1, 1), (2, 1), (2, 2)])
    check(MultiLoops, "1 1", [(1, 1)])
end

# * Anonym ...................................................................

module Anonym
using ReTest, ..Trace

@testset for x=1:2
    @testset begin
        trace(x)
    end
end
end # Anonym

@chapter Anonym check(Anonym, [1, 2])

# * loop variable collision ..................................................

module LoopCollision
using ReTest, ..Trace

@assert isdefined(LoopCollision, :sincos)
@assert isdefined(LoopCollision, :sinpi)

@testset "collision $sincos" for sincos in (sin, cos)
    @test sincos(1.0) isa Float64
    trace(sincos)
end

@testset "collision $sincos sinpi $sinpi" for sincos = (sin, cos), sinpi = (1,)
    trace((sincos, sinpi))
end

end # LoopCollision

@chapter LoopCollision begin
    retest(LoopCollision, dry=true)
    check(LoopCollision, [sin, cos, (sin, 1), (cos, 1)]; dry=false)
end

# * interpolated description .................................................

module Interpolate
using ReTest, ..Trace

X = 0

@testset "a $X" verbose=true begin
    @testset "b $X" begin
        trace(1)
    end
    @testset "c $X $i" for i=2:3
        trace(i)
    end
end

@testset "d $X $i" verbose=true for i=4:4
    trace(i)
    @testset "e $X" begin
        trace(5)
    end
end
end # Interpolate

@chapter Interpolate begin
    retest(Interpolate, dry=true)
    check(Interpolate, 1:5)
    check(Interpolate, "0", 1:5)
    check(Interpolate, "4", 4:5)
end

module InterpolateImpossible
using ReTest, ..Trace

X = 0

@testset "a $X" verbose=true begin
    trace(0)
    j = 9
    @testset "b $X $j" begin
        trace(1)
    end
    @testset "c $X $j $i" for i=2:3
        trace(i)
    end
end

@testset "d $X $i" verbose=true for i=4:4
    trace(i)
    @testset "e $X $i" begin
        trace(5)
    end
    @testset "$i" begin # must work even "$i" is made only of Expr (no String parts)
        trace(6)
    end
end
end # InterpolateImpossible

@chapter Interpolate begin
    retest(InterpolateImpossible, dry=true)
    check(InterpolateImpossible, 0:6)
    check(InterpolateImpossible, "0", 0:6)
    check(InterpolateImpossible, "4", [0, 4, 5, 6]) # should have a warning or two
    check(InterpolateImpossible, "d", not(2:3), 4:6)
end

# * Failing ..................................................................

module Failing
using ReTest

@testset "has fails" begin
    @test false
end
end # Failing

@chapter Failing @test_throws Test.TestSetException retest(Failing)

# * Duplicate ................................................................

module Duplicate
using ReTest

RUN = []

@testset "dupe" begin
    @test true
    push!(RUN, 1)
end
@testset "dupe" begin
    @test true
    push!(RUN, 2)
end

@testset "dupe$i" for i=3:4
    @test true
    push!(RUN, i)
end
@testset "dupe$i" for i=5:6
    @test true
    push!(RUN, i)
end
end # Duplicate

@chapter Duplicate begin
    @test_logs (
        :warn, r"duplicate description for @testset, overwriting:.*") (
        :warn,  r"duplicate description for @testset, overwriting:.*"
        )  Duplicate.runtests()
    @test Duplicate.RUN == [2, 5, 6]

    # uniquify
    empty!(Duplicate.RUN)
    retest(Duplicate, Duplicate, "dupe5")
    @test Duplicate.RUN == [5]
end

# * Display ..................................................................

# we exercise a bunch of codepaths, and this allows to have an idea whether
# everything prints properly (writing proper display tests will be soooo boring)

module X
using ReTest

@testset "X.full" begin
    @test true
    @testset "X.inner" begin
    end
end
end # X

module YYYYYYYYYYYYY
using ReTest

@testset "Y.broken" begin
    @testset "hidden" begin
        # we "hide" it to be sure that the .hasbrokenrec field is used and not .hasbroken
        @test_broken false
    end
end
@testset "Y.loop $('*'^(10-3*i))" for i=1:2
    @test true
    @testset "Y.inner_____________" begin
        @test true
        @testset "Y.core" begin
            @test true
        end
    end
end
end # YYYYYYYYYYYYY

module NoTests
using ReTest

@testset "empty" begin end
@testset "empty $i" for i=1:1 end
end # NoTests

@chapter Display for dry=(true, false),
    verbose=0:3,
    stats=(true, false),
    mod=((X,), (YYYYYYYYYYYYY,), (X, YYYYYYYYYYYYY), (NoTests,)),
    pattern=(r"inner", 1:99, "not matching")

    id=rand([true, false, nothing])
    if pattern == "not matching"
        mod in [(X,), (X, YYYYYYYYYYYYY)] || continue
        verbose in 0:1 || continue
    end
    if mod == (NoTests,)
        dry == false && verbose in 0:1 && pattern == 1:99 ||
            continue
    end
    modstr = length(mod) == 1 ? string(mod[1]) : string(mod)
    # have to show 'X' below, because `nothing` can't be printed on old Julia
    println("\n####################### Display: mod=$modstr stats=$stats dry=$dry verbose=$verbose pattern=$pattern, id=$(something(id, 'X'))\n")
    retest(mod..., pattern; shuffle=true, verbose=verbose, stats=stats, dry=dry, id=id)
end

# * DryRun ...................................................................

module DryRun
using ReTest

X = 'a'

@testset "a" for i=1:2
    @testset "b" begin end
end
@testset "a$X" for i=1:2
    @testset "b" begin end
end
@testset "x$i" for i=1:2
    @testset "b$i" begin
        @testset "c" begin end
    end
    @testset "d$i$j" for j=1:2
    end
end
@testset "y$i" for i=1:1
    @testset "b" for j=1:i
        @testset "c" begin end
    end
end

end # DryRun

@chapter DryRun begin
    retest(DryRun, dry=true)
    retest(DryRun, dry=true, verbose=0)
    retest(DryRun, dry=true, verbose=5)
end

module DryRun2
using ReTest

@testset "just a dummy module" begin end
end # DryRun2

@chapter DryRun begin
    retest(DryRun, DryRun2, dry=true, verbose=0)
    retest(DryRun, DryRun2, dry=true, verbose=1)
end

# * InlineTest ...............................................................

@chapter InlineTest begin
    using Pkg
    Pkg.activate("./FakePackage")
    Pkg.develop(PackageSpec(path="../InlineTest"))
    Pkg.develop(PackageSpec(path="..")) # ReTest
    Pkg.test("FakePackage")
end

# * Hijack ...................................................................

@chapter Hijack begin
    Pkg.activate("./Hijack")
    Pkg.develop(PackageSpec(path="..")) # ReTest
    Pkg.test("Hijack")

    if VERSION >= v"1.5"

        using Hijack
        ReTest.hijack(Hijack)
        retest(HijackTests)
        @test Hijack.RUN == [1]
        empty!(Hijack.RUN)

        @test_throws ErrorException ReTest.hijack(Hijack, :HijackTests2, revise=true)

        using Revise
        ReTest.hijack(Hijack, :HijackTests2, revise=true)
        retest(HijackTests2)
        @test Hijack.RUN == [1]
        empty!(Hijack.RUN)

        cp("./Hijack/test/subdir/sub.jl",
           "./Hijack/test/subdir/sub.orig.jl", force=true)

        write("./Hijack/test/subdir/sub.jl",
              """
@test true

@testset "sub" begin
    @test true
    @test true
    push!(Hijack.RUN, 2)
end
""")
        Revise.revise()
        try
            retest(HijackTests2)
            @test Hijack.RUN == [2]
        finally
            mv("./Hijack/test/subdir/sub.orig.jl",
               "./Hijack/test/subdir/sub.jl", force=true)
        end
    end
end


text:
# ---
# title: 517. Super Washing Machines
# id: problem517
# author: Tian Jun
# date: 2020-10-31
# difficulty: Hard
# categories: Math, Dynamic Programming
# link: <https://leetcode.com/problems/super-washing-machines/description/>
# hidden: true
# ---
#
# You have **n** super washing machines on a line. Initially, each washing
# machine has some dresses or is empty.
#
# For each **move** , you could choose **any m** (1 ≤ m ≤ n) washing machines,
# and pass **one dress** of each washing machine to one of its adjacent washing
# machines **at the same time**.
#
# Given an integer array representing the number of dresses in each washing
# machine from left to right on the line, you should find the **minimum number
# of moves** to make all the washing machines have the same number of dresses.
# If it is not possible to do it, return -1.
#
# **Example1**
#
#
#
#     Input: [1,0,5]
#
#     Output: 3
#
#     Explanation:
#     1st move:    1     0 <-- 5    =>    1     1     4
#     2nd move:    1 <-- 1 <-- 4    =>    2     1     3
#     3rd move:    2     1 <-- 3    =>    2     2     2
#
#
# **Example2**
#
#
#
#     Input: [0,3,0]
#
#     Output: 2
#
#     Explanation:
#     1st move:    0 <-- 3     0    =>    1     2     0
#     2nd move:    1     2 --> 0    =>    1     1     1
#
#
# **Example3**
#
#
#
#     Input: [0,2,0]
#
#     Output: -1
#
#     Explanation:
#     It's impossible to make all the three washing machines have the same number of dresses.
#
#
# **Note:**
#
#   1. The range of n is [1, 10000].
#   2. The range of dresses number in a super washing machine is [0, 1e5].
#
#
## @lc code=start
using LeetCode

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

ext: jl


text:
abstract type AbstractAction{T} end

struct OnPoints{T} <: AbstractAction{T}
    features::Vector{T}
    reversef::Dict{T, Int}
end

Base.getindex(act::OnPoints, i::Integer) = act.features[i]
Base.getindex(act::OnPoints{T}, f::T) where T = act.reversef[f]
(act::OnPoints)(p::Perm{I}) where I = Perm(I[act[f^p] for f in act.features])

function (act::OnPoints)(orb::O) where {T, O<:AbstractOrbit{T, Nothing}}
    elts = act.(orb)
    dict = Dict(e=>nothing for e in elts)
    return O(elts, dict)
end


text:
# syntax: proto3
using ProtoBuf
import ProtoBuf.meta

const MillTypes = (;[
    Symbol("A") => Int32(0),
    Symbol("B") => Int32(1),
]...)

const MoveType = (;[
    Symbol("MoveToPickup") => Int32(0),
    Symbol("PickupAndDropoff") => Int32(1),
]...)

const StackTypes = (;[
    Symbol("ArrivalStack") => Int32(0),
    Symbol("ShuffleBuffer") => Int32(1),
    Symbol("SortedBuffer") => Int32(2),
    Symbol("HandoverStack") => Int32(3),
]...)

mutable struct CraneScheduleActivity <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function CraneScheduleActivity(; kwargs...)
        obj = new(meta(CraneScheduleActivity), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct CraneScheduleActivity

const __meta_CraneScheduleActivity = Ref{ProtoMeta}()

function meta(::Type{CraneScheduleActivity})
    ProtoBuf.metalock() do
        if !isassigned(__meta_CraneScheduleActivity)
            __meta_CraneScheduleActivity[] = target = ProtoMeta(CraneScheduleActivity)
            allflds = Pair{Symbol,Union{Type,String}}[:MoveId => Int32, :CraneId => Int32, :Priority => Int32]
            meta(target, CraneScheduleActivity, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_CraneScheduleActivity[]
    end
end

function Base.getproperty(obj::CraneScheduleActivity, name::Symbol)
    if name === :MoveId
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :CraneId
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :Priority
        return (obj.__protobuf_jl_internal_values[name])::Int32
    else
        getfield(obj, name)
    end
end

mutable struct CraneSchedule <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function CraneSchedule(; kwargs...)
        obj = new(meta(CraneSchedule), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct CraneSchedule

const __meta_CraneSchedule = Ref{ProtoMeta}()

function meta(::Type{CraneSchedule})
    ProtoBuf.metalock() do
        if !isassigned(__meta_CraneSchedule)
            __meta_CraneSchedule[] = target = ProtoMeta(CraneSchedule)
            allflds = Pair{Symbol,Union{Type,String}}[:ScheduleNr => Int32, :Activities => Base.Vector{CraneScheduleActivity}]
            meta(target, CraneSchedule, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_CraneSchedule[]
    end
end

function Base.getproperty(obj::CraneSchedule, name::Symbol)
    if name === :ScheduleNr
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :Activities
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{CraneScheduleActivity}
    else
        getfield(obj, name)
    end
end

mutable struct Performance <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Performance(; kwargs...)
        obj = new(meta(Performance), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct Performance

const __meta_Performance = Ref{ProtoMeta}()

function meta(::Type{Performance})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Performance)
            __meta_Performance[] = target = ProtoMeta(Performance)
            allflds = Pair{Symbol,Union{Type,String}}[:CraneManipulations => Int32, :ServiceLevelMean => Float64, :LeadTimeMean => Float64, :DeliveredBlocks => Int32, :TotalBlocksOnTime => Int32, :TardinessMean => Float64, :ShuffleBufferUtilizationMean => Float64, :SortedBufferUtilizationMean => Float64, :ShuffleCraneUtilizationMean => Float64, :HandoverCraneUtilizationMean => Float64, :MillAUtilizationMean => Float64, :MillBUtilizationMean => Float64, :RollingProgramMessups => Int32, :BlockedMillTime => Float64]
            meta(target, Performance, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_Performance[]
        end
end

function Base.getproperty(obj::Performance, name::Symbol)
    if name === :CraneManipulations
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :ServiceLevelMean
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :LeadTimeMean
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :DeliveredBlocks
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :TotalBlocksOnTime
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :TardinessMean
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :ShuffleBufferUtilizationMean
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :SortedBufferUtilizationMean
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :ShuffleCraneUtilizationMean
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :HandoverCraneUtilizationMean
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :MillAUtilizationMean
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :MillBUtilizationMean
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :RollingProgramMessups
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :BlockedMillTime
        return (obj.__protobuf_jl_internal_values[name])::Float64
    else
        getfield(obj, name)
    end
end

mutable struct TimeStamp <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function TimeStamp(; kwargs...)
        obj = new(meta(TimeStamp), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct TimeStamp

const __meta_TimeStamp = Ref{ProtoMeta}()

function meta(::Type{TimeStamp})
    ProtoBuf.metalock() do
        if !isassigned(__meta_TimeStamp)
            __meta_TimeStamp[] = target = ProtoMeta(TimeStamp)
            allflds = Pair{Symbol,Union{Type,String}}[:MilliSeconds => Int64]
            meta(target, TimeStamp, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_TimeStamp[]
    end
end

function Base.getproperty(obj::TimeStamp, name::Symbol)
    if name === :MilliSeconds
    return (obj.__protobuf_jl_internal_values[name])::Int64
    else
        getfield(obj, name)
    end
end

mutable struct CraneMove <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function CraneMove(; kwargs...)
        obj = new(meta(CraneMove), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct CraneMove

const __meta_CraneMove = Ref{ProtoMeta}()

function meta(::Type{CraneMove})
    ProtoBuf.metalock() do
        if !isassigned(__meta_CraneMove)
            __meta_CraneMove[] = target = ProtoMeta(CraneMove)
            fnum = Int[1,2,3,4,7,8,9,10,11]
            pack = Symbol[:ProtobufPredecessorIds]
            allflds = Pair{Symbol,Union{Type,String}}[:Id => Int32, :_Type => Int32, :PickupLocationId => Int32, :DropoffLocationId => Int32, :Amount => Int32, :ReleaseTime => TimeStamp, :DueDate => TimeStamp, :RequiredCraneId => Int32, :ProtobufPredecessorIds => Base.Vector{Int32}]
            meta(target, CraneMove, allflds, ProtoBuf.DEF_REQ, fnum, ProtoBuf.DEF_VAL, pack, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_CraneMove[]
    end
end

function Base.getproperty(obj::CraneMove, name::Symbol)
    if name === :Id
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :_Type
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :PickupLocationId
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :DropoffLocationId
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :Amount
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :ReleaseTime
        return (obj.__protobuf_jl_internal_values[name])::TimeStamp
    elseif name === :DueDate
        return (obj.__protobuf_jl_internal_values[name])::TimeStamp
    elseif name === :RequiredCraneId
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :ProtobufPredecessorIds
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Int32}
    else
        getfield(obj, name)
    end
end

    mutable struct Block <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Block(; kwargs...)
        obj = new(meta(Block), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct Block

const __meta_Block = Ref{ProtoMeta}()

function meta(::Type{Block})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Block)
            __meta_Block[] = target = ProtoMeta(Block)
            allflds = Pair{Symbol,Union{Type,String}}[:Id => Int32, :Sequence => Int32, :_Type => Int32, :ProgramId => Int32, :Arrived => TimeStamp, :Rolled => Bool]
            meta(target, Block, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_Block[]
    end
end

function Base.getproperty(obj::Block, name::Symbol)
    if name === :Id
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :Sequence
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :_Type
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :ProgramId
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :Arrived
        return (obj.__protobuf_jl_internal_values[name])::TimeStamp
    elseif name === :Rolled
        return (obj.__protobuf_jl_internal_values[name])::Bool
    else
        getfield(obj, name)
    end
end

mutable struct MoveRequest <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function MoveRequest(; kwargs...)
        obj = new(meta(MoveRequest), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
        fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct MoveRequest

const __meta_MoveRequest = Ref{ProtoMeta}()

function meta(::Type{MoveRequest})
    ProtoBuf.metalock() do
        if !isassigned(__meta_MoveRequest)
            __meta_MoveRequest[] = target = ProtoMeta(MoveRequest)
            allflds = Pair{Symbol,Union{Type,String}}[:Id => Int32, :TargetLocationId => Int32, :BlockId => Int32, :DueDate => TimeStamp]
            meta(target, MoveRequest, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_MoveRequest[]
    end
end

function Base.getproperty(obj::MoveRequest, name::Symbol)
    if name === :Id
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :TargetLocationId
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :BlockId
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :DueDate
        return (obj.__protobuf_jl_internal_values[name])::TimeStamp
    else
        getfield(obj, name)
    end
end

mutable struct PlannedCraneMoves <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function PlannedCraneMoves(; kwargs...)
        obj = new(meta(PlannedCraneMoves), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct PlannedCraneMoves

const __meta_PlannedCraneMoves = Ref{ProtoMeta}()

function meta(::Type{PlannedCraneMoves})
    ProtoBuf.metalock() do
        if !isassigned(__meta_PlannedCraneMoves)
            __meta_PlannedCraneMoves[] = target = ProtoMeta(PlannedCraneMoves)
            allflds = Pair{Symbol,Union{Type,String}}[:SequenceNr => Int32, :Moves => Base.Vector{CraneMove}]
            meta(target, PlannedCraneMoves, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_PlannedCraneMoves[]
    end
end

function Base.getproperty(obj::PlannedCraneMoves, name::Symbol)
    if name === :SequenceNr
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :Moves
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{CraneMove}
    else
        getfield(obj, name)
        end
end

mutable struct Stack <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Stack(; kwargs...)
        obj = new(meta(Stack), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct Stack

const __meta_Stack = Ref{ProtoMeta}()

function meta(::Type{Stack})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Stack)
            __meta_Stack[] = target = ProtoMeta(Stack)
            allflds = Pair{Symbol,Union{Type,String}}[:BottomToTop => Base.Vector{Block}]
            meta(target, Stack, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_Stack[]
    end
end

function Base.getproperty(obj::Stack, name::Symbol)
    if name === :BottomToTop
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Block}
    else
        getfield(obj, name)
    end
end

mutable struct Location <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Location(; kwargs...)
        obj = new(meta(Location), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct Location

const __meta_Location = Ref{ProtoMeta}()

function meta(::Type{Location})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Location)
            __meta_Location[] = target = ProtoMeta(Location)
            allflds = Pair{Symbol,Union{Type,String}}[:Id => Int32, :GirderPosition => Float64, :MaxHeight => Int32, :Stack => Stack, :_Type => Int32, :MillType => Int32]
            meta(target, Location, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_Location[]
    end
end

function Base.getproperty(obj::Location, name::Symbol)
    if name === :Id
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :GirderPosition
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :MaxHeight
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :Stack
        return (obj.__protobuf_jl_internal_values[name])::Stack
    elseif name === :_Type
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :MillType
        return (obj.__protobuf_jl_internal_values[name])::Int32
    else
        getfield(obj, name)
    end
end

mutable struct Arrival <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Arrival(; kwargs...)
        obj = new(meta(Arrival), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct Arrival

const __meta_Arrival = Ref{ProtoMeta}()

function meta(::Type{Arrival})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Arrival)
            __meta_Arrival[] = target = ProtoMeta(Arrival)
            allflds = Pair{Symbol,Union{Type,String}}[:Vehicle => Int32, :Load => Stack, :ArrivalEstimate => TimeStamp]
            meta(target, Arrival, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_Arrival[]
    end
end

function Base.getproperty(obj::Arrival, name::Symbol)
    if name === :Vehicle
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :Load
        return (obj.__protobuf_jl_internal_values[name])::Stack
    elseif name === :ArrivalEstimate
        return (obj.__protobuf_jl_internal_values[name])::TimeStamp
    else
        getfield(obj, name)
    end
end

mutable struct Crane <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

    function Crane(; kwargs...)
        obj = new(meta(Crane), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct Crane

const __meta_Crane = Ref{ProtoMeta}()

function meta(::Type{Crane})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Crane)
            __meta_Crane[] = target = ProtoMeta(Crane)
allflds = Pair{Symbol,Union{Type,String}}[:Id => Int32, :Load => Stack, :GirderPosition => Float64, :HoistLevel => Float64, :CraneCapacity => Int32, :Width => Float64, :MinPosition => Float64, :MaxPosition => Float64]
            meta(target, Crane, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_Crane[]
    end
end

function Base.getproperty(obj::Crane, name::Symbol)
    if name === :Id
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :Load
        return (obj.__protobuf_jl_internal_values[name])::Stack
    elseif name === :GirderPosition
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :HoistLevel
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :CraneCapacity
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :Width
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :MinPosition
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :MaxPosition
        return (obj.__protobuf_jl_internal_values[name])::Float64
    else
        getfield(obj, name)
    end
end

mutable struct Uncertainties <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}

    function Uncertainties(; kwargs...)
        obj = new(meta(Uncertainties), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct Uncertainties

const __meta_Uncertainties = Ref{ProtoMeta}()

function meta(::Type{Uncertainties})
    ProtoBuf.metalock() do
        if !isassigned(__meta_Uncertainties)
            __meta_Uncertainties[] = target = ProtoMeta(Uncertainties)
pack = Symbol[:ArrivalIntervals,:CraneMoveTimes,:MillBlockIntervals]
            allflds = Pair{Symbol,Union{Type,String}}[:ArrivalIntervals => Base.Vector{Float64}, :CraneMoveTimes => Base.Vector{Float64}, :MillBlockIntervals => Base.Vector{Float64}]
            meta(target, Uncertainties, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, pack, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_Uncertainties[]
    end
end

function Base.getproperty(obj::Uncertainties, name::Symbol)
    if name === :ArrivalIntervals
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Float64}
    elseif name === :CraneMoveTimes
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Float64}
    elseif name === :MillBlockIntervals
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Float64}
    else
        getfield(obj, name)
    end
end

mutable struct World <: ProtoType
    __protobuf_jl_internal_meta::ProtoMeta
    __protobuf_jl_internal_values::Dict{Symbol,Any}
    __protobuf_jl_internal_defaultset::Set{Symbol}

        function World(; kwargs...)
        obj = new(meta(World), Dict{Symbol,Any}(), Set{Symbol}())
        values = obj.__protobuf_jl_internal_values
        symdict = obj.__protobuf_jl_internal_meta.symdict
        for nv in kwargs
            fldname, fldval = nv
            fldtype = symdict[fldname].jtyp
            (fldname in keys(symdict)) || error(string(typeof(obj), " has no field with name ", fldname))
            values[fldname] = isa(fldval, fldtype) ? fldval : convert(fldtype, fldval)
        end
        obj
    end
end # mutable struct World

const __meta_World = Ref{ProtoMeta}()

function meta(::Type{World})
    ProtoBuf.metalock() do
        if !isassigned(__meta_World)
            __meta_World[] = target = ProtoMeta(World)
            allflds = Pair{Symbol,Union{Type,String}}[:Now => TimeStamp, :Height => Int32, :Width => Float64, :Locations => Base.Vector{Location}, :BlocksAtSlabYard => Base.Vector{Block}, :ArrivalsFromSlabYard => Base.Vector{Arrival}, :CraneMoves => PlannedCraneMoves, :MoveRequests => Base.Vector{MoveRequest}, :CraneSchedule => CraneSchedule, :ShuffleCrane => Crane, :HandoverCrane => Crane, :KPIs => Performance, :ObservationData => Uncertainties]
            meta(target, World, allflds, ProtoBuf.DEF_REQ, ProtoBuf.DEF_FNUM, ProtoBuf.DEF_VAL, ProtoBuf.DEF_PACK, ProtoBuf.DEF_WTYPES, ProtoBuf.DEF_ONEOFS, ProtoBuf.DEF_ONEOF_NAMES)
        end
        __meta_World[]
    end
end

function Base.getproperty(obj::World, name::Symbol)
    if name === :Now
        return (obj.__protobuf_jl_internal_values[name])::TimeStamp
    elseif name === :Height
        return (obj.__protobuf_jl_internal_values[name])::Int32
    elseif name === :Width
        return (obj.__protobuf_jl_internal_values[name])::Float64
    elseif name === :Locations
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Location}
    elseif name === :BlocksAtSlabYard
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Block}
    elseif name === :ArrivalsFromSlabYard
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{Arrival}
    elseif name === :CraneMoves
        return (obj.__protobuf_jl_internal_values[name])::PlannedCraneMoves
    elseif name === :MoveRequests
        return (obj.__protobuf_jl_internal_values[name])::Base.Vector{MoveRequest}
    elseif name === :CraneSchedule
        return (obj.__protobuf_jl_internal_values[name])::CraneSchedule
    elseif name === :ShuffleCrane
        return (obj.__protobuf_jl_internal_values[name])::Crane
    elseif name === :HandoverCrane
        return (obj.__protobuf_jl_internal_values[name])::Crane
    elseif name === :KPIs
        return (obj.__protobuf_jl_internal_values[name])::Performance
    elseif name === :ObservationData
        return (obj.__protobuf_jl_internal_values[name])::Uncertainties
    else
        getfield(obj, name)
    end
end

export MillTypes, MoveType, StackTypes, Arrival, Block, Crane, CraneMove, CraneSchedule, CraneScheduleActivity, Location, MoveRequest, Performance, PlannedCraneMoves, Stack, TimeStamp, Uncertainties, World


text:
function makeFileList(path, suffixIdentifier)

  fileList = Vector{String}()
  for (root, dirs, files) in walkdir(path)
      rootList = split(root,"\\")
    for file in files
      if last(file, length(suffixIdentifier)) == suffixIdentifier
        push!(rootList, file)
        push!(fileList, join(rootList, "\\"))
      end
    end
  end

  return fileList
end


text:
#! /usr/bin/julia

# Rosetta Code, URL encoding

using URIParser

dcd = "http://foo bar/"
enc = escape(dcd)

println(dcd, " => ", enc)

max_stars_repo_name: MichaeLeroy/rosetta-code

max_issues_repo_name: MichaeLeroy/rosetta-code

max_forks_repo_name: MichaeLeroy/rosetta-code


text:
abstract type DependencyTreeError <: Exception end

"""
    NonProjectiveGraphError

Error trying to parse a nonprojective tree with a projective only algorithm.
"""
struct NonProjectiveGraphError <: DependencyTreeError
    tree
end

"""
    MultiWordTokenError

Error for a multi-token annotation that isn't part of the tree.
"""
struct MultiWordTokenError <: DependencyTreeError
    token
end

"""
    EmptyTokenError

Error for an empty token annotation that isn't part of the tree.
"""
struct EmptyTokenError <: DependencyTreeError
    token
end


text:
using Base: readlines
using Base: ==

function parse_matrix(io)
    rows = []
    for line in eachline(io)
        push!(rows, parse.(Int8, collect(line)))
    end
    return transpose(hcat(rows...))
end

function parse_point(s::AbstractString)
    nums = split(s, ',')
    return [parse(Int, nums[1])+1, parse(Int, nums[2])+1]
end

struct Segment
    p1 :: Vector{Int}
    p2 :: Vector{Int}
end

function parse_segment(s::AbstractString)
    parts = split(s)
    # Intentionally leave out parts[2], it is "->"
    return Segment(parse_point(parts[1]), parse_point(parts[3]))
end

function Base.:(==)(s1::Segment, s2::Segment)
    return s1.p1 == s2.p1 && s1.p2 == s2.p2
end

function parse_segments(io)
    return parse_segment.(readlines(io))
end

"Split a text file by empty lines and return all the parts as list of strings each."
function parse_parts(io)
    segments = []
    segment = []
    for line in eachline(io)
        line = strip(line)
        if isempty(line)
            if !isempty(segment)
                push!(segments, segment)
            end
            segment = []
        else
            push!(segment, line)
        end
    end
    if !isempty(segment)
        push!(segments, segment)
    end
    return segments
end

mutable struct Bingo
    numbers::Vector{Int}
    boards::Vector{Matrix{Int}}
end

parse_ints_from_row(str; sep = " ") = parse.(Int, split(str, sep, keepempty = false))

function parse_bingo(fpath::AbstractString)
    segments = parse_parts(fpath)
    nbrs = parse_ints_from_row(segments[1][1], sep=',')
    boards = parse_bingo_board.(segments[2:end])
    return Bingo(nbrs, boards)
end

function parse_bingo_board(segment)
    rows = parse_ints_from_row.(segment)
    return vcat((rows')...)
end

parseint(x) = parse(Int, x)

function parsebinary(fpath::AbstractString)
    lines = readlines(fpath)
    binmatrix = parse.(Int, reduce(vcat, permutedims.(collect.(lines))))
    return binmatrix
end

function parseints(fpath::AbstractString)
    lines = readlines(fpath)
    numbers = parseint.(lines)
    return numbers
end

function parsecommand(line::AbstractString)
    parts = split(line, limit = 2)
    return (parts[1], parseint(parts[2]))
end

function parsecommands(fpath::AbstractString)
    lines = readlines(fpath)
    return [parsecommand(line) for line ∈ lines]
end

function readmatrix(filename::AbstractString)
    lines = readlines(filename)
    mat = Array{Char}(undef, length(lines), length(lines[1]))
    for (r, row) in enumerate(lines)
        for (c, item) in enumerate(row)
            mat[r, c] = item
        end
    end
    return mat
end

function item(mat::Matrix, r::Int, c::Int)
    n_rows, n_columns = size(mat)
    c = mod(c - 1, n_columns) + 1
    return mat[r, c]
end


text:
# Guizar-Sicairos2004JotOSoAA - Computation of quasi-discrete Hankel transforms of integer order for propagating optical wave fields

#=
Calculates an approximation to
\[f_2(\nu) = 2\pi\int\limits_0^\infty dr\; r f_1(r)J_p(2\pi \nu r)\]

as \[\vec{F}_2=\mathsf{T}\vec{F}_1\]

where \[\vec{F}_2(m)=\left\{\frac{f_2\left(\frac{\alpha_{pm}}{2\pi R}\right)V}{|J_{p+1}(\alpha_{pm})|}\right\}\],
\[\vec{F}_1(n)=\left\{\frac{f_1\left(\frac{\alpha_{pn}}{2\pi V}\right)R}{|J_{p+1}(\alpha_{pn})|}\right\}\],
and \[\mathsf{T}_{mn}=\frac{2J_p(\alpha_{pn}\alpha_{pm}/S)}{|J_{p+1}(\alpha_{pn})||J_{p+1}(\alpha_{pm})|S}\].

\(R\) is maximum radius, \(V\) the maximum frequency and \(S=2\pi RV\).

\(f_1\) is assumed to be sampled on these gridpoints.
=#

export Guizar, guizar

using GSL

type Guizar
    p::Int
    R
    N::Int
    r
    ν
    V
    Jp1
    T
end

function Guizar(p::Int, R, N::Int)
    α = sf_bessel_zero_Jnu(p, 1:N)
    αNp1 = sf_bessel_zero_Jnu(p, N+1)
    r = α*R/αNp1
    ν = α/(2π*R)
    V = αNp1/(2π*R)
    S = 2π*R*V
    Jp1 = abs(besselj(p+1,α))
    T = 2besselj(p,(α*α')/S)./(S*Jp1*Jp1')
    Guizar(p,R,N,r,ν,V,Jp1,T)
end

function (gt::Guizar)(v::AbstractArray)
    F1 = (v./gt.Jp1)*gt.R
    F2 = gt.T*F1
    gt.ν,F2.*gt.Jp1/gt.V
end

function (gt::Guizar)(f1::Function)
    gt(f1(gt.r))
end

function guizar(f1, p::Int, R, N::Int)
    Guizar(p,R,N)(f1)
end


text:
# This file is a part of RunStatistics.jl, licensed under the MIT License (MIT).

export squares_cdf_approx, squares_pvalue_approx

"""
    IntegrandData

Represent the parameters needed for the 1D numerical integration performed in `Delta()`.

`T_obs` is the value for the Squares statistic observed in the data, `Nl` the left-hand length and
`Nr` the right-hand length of a boundary spanning run, as defined in section II.A. in

Frederik Beaujean and Allen Caldwell. *Is the bump significant? An axion-search example*

https://arxiv.org/abs/1710.06642
"""
mutable struct IntegrandData
    T_obs::Float64
    Nl::Int
    Nr::Int
end

"""
    h(chisq::Real, N::Integer)

Compute the probability density h(χ2 | Nr) for the right-hand side of a boundary spanning
run to be above expectation;
as explained in section II.A. in the paper below.

Calculate it as the sum of probability densities for runs of different length times the χ2
    probability for that number of degrees of freedom.

Implements the term defined in equation (8) in

Frederik Beaujean and Allen Caldwell. *Is the bump significant? An axion-search example*

https://arxiv.org/abs/1710.06642
"""
function h(chisq::Real, N::Integer)
    res = 0
    weight = 0.5

    for i = 1:N
        if (i < N)
            weight *= 0.5
        end
        res += weight * pdf(Chisq(i), chisq)
    end

    return res
end

"""
    H(a::Real, b::Real, N::Integer)

Compute the cumulative of `h()` as defined in section II.A. in

Frederik Beaujean and Allen Caldwell. *Is the bump significant? An axion-search example*

https://arxiv.org/abs/1710.06642
"""
function H(a::Real, b::Real, N::Integer)

    res = 0
    weight = 0.5

    for i = 1:N
        if (i < N)
            weight *= 0.5
        end

        res += weight * (cdf(Chisq(i), b) - cdf(Chisq(i), a))
    end

    return res
end

"""
    (integrand::IntegrandData)(x::Real)

Compute the integrand in the Δ(T_obs | N_l, N_r) term defined in equation (13) in

Frederik Beaujean and Allen Caldwell. *Is the bump significant? An axion-search example*

https://arxiv.org/abs/1710.06642
"""
function (integrand::IntegrandData)(x::Real)
    return h(x, integrand.Nl) * H(integrand.T_obs - x, integrand.T_obs, integrand.Nr)
end

"""
    Delta(T_obs::Real, Nl::Integer, Nr::Integer, epsrel::Real, epsabs::Real)

Compute the Δ(T_obs | N_l, N_r) term defined in equation (13) in

Frederik Beaujean and Allen Caldwell. *Is the bump significant? An axion-search example*

https://arxiv.org/abs/1710.06642

The calculation involves a 1D numerical integration using the `quadgk()` function with the
relative and absolute target precision `epsrel` and `epsabs`. If not specified, the default
values of `quadgk()` are used.
See https://juliamath.github.io/QuadGK.jl/stable/ for documentation.
"""
function Delta(T_obs::Real, Nl::Integer, Nr::Integer, epsrel::Nothing = nothing, epsabs::Real = nothing)

    F = IntegrandData(T_obs, Nl, Nr)
    return quadgk(F, 0, T_obs, rtol = epsrel, atol = epsabs, order = 10)
end

"""
squares_cdf_approx(T_obs::Real, L::Integer, [epsp::Real])

Compute an approximation of P(T < `T_obs` | `L = n * N`), the value of the cumulative distribution
function for the Squares test statistic at `T_obs`,
the value of the Squares statistic observed in the data.
The total number of datapoints is `L = n * N`, if not defined otherwise, the function chooses the default values `N = 80` and `n = L / N`.

The accuracy's lower bound is `10^(-14)`, a desired accuracy up to this boundary can be specified with the optional `epsp` argument.
See documentation on Accuracy.

This function implements equation (17) from:

Frederik Beaujean and Allen Caldwell. *Is the bump significant? An axion-search example*

https://arxiv.org/abs/1710.06642

"""
function squares_cdf_approx(T_obs::Real, L::Integer, epsp::Real = 0)
    N = 80
    n = L / N

    @argcheck (epsp == 0 || epsp / n >= 10^(-14)) error("The desired accuracy is too high. See documentation on Accuracy.")

    if epsp != 0

        epsabs = (epsp / n) * 0.1
        F = squares_cdf(T_obs, N)
        Fn1 = (F / (1 + Delta(T_obs, N, N, nothing, epsabs)[1]))^(n - 1)
        return F * Fn1
    end

    F = squares_cdf(T_obs, N)
    Fn1 = (F / (1 + Delta(T_obs, N, N)[1]))^(n - 1)
    return F * Fn1
end

function squares_cdf_approx(T_obs::Real, N::Integer, n::Real,  epsp::Real = 0)

    @argcheck (epsp == 0 || epsp / n >= 10^(-14)) error("The desired accuracy is too high. See documentation on Accuracy.")

    if epsp != 0

        epsabs = (epsp / n) * 0.1
        F = squares_cdf(T_obs, N)
        Fn1 = (F / (1 + Delta(T_obs, N, N, nothing, epsabs)[1]))^(n - 1)
        return F * Fn1
    end

    F = squares_cdf(T_obs, N)
    Fn1 = (F / (1 + Delta(T_obs, N, N)[1]))^(n - 1)
    return F * Fn1
end

"""
    squares_pvalue_approx(T_obs::Real, N::Integer, n::Real, [epsrel::Real, epsabs::Real])

Compute an approximation of P(T >= `T_obs` | `n * N`), the p value for the Squares test
statistic T being larger or equal to `T_obs`,
the value of the Squares statistic observed in the data.
The total number of datapoints is `L = n * N`, if not defined otherwise, the function chooses the default values `N = 80` and `n = L / N`.

The accuracy's lower bound is `10^(-14)`, a desired accuracy up to this boundary can be specified with the optional `epsp` argument.
See documentation on Accuracy.

Via `squares_cdf_approx()` this function implements equation (17) from:

Frederik Beaujean and Allen Caldwell. *Is the bump significant? An axion-search example*

https://arxiv.org/abs/1710.06642

"""
function squares_pvalue_approx(T_obs::Real, L::Integer,  epsp::Real = 0)

    return 1 - squares_cdf_approx(T_obs, L, epsp)
end

function squares_pvalue_approx(T_obs::Real, N::Integer, n::Real,  epsp::Real = 0)

    return 1 - squares_cdf_approx(T_obs, N, n, epsp)
end


text:
using ShaderToy
shadertoy("monster.frag")


text:
"""
    padbed(bedfile::String, pad::Int64)

Add padding to left and right coordinates of a bedfile.
"""
function padbed(bedfile::String, pad::Int64)

    m = readdlm(bedfile)

    w = pad / 2

    chrs = (m[:,1])
    p1 = BigInt.(m[:,2] .- w)
    p2 = BigInt.(m[:,3] .+ w)

    nb = hcat(string.(chrs), string.(p1), string.(p2))
    newpos = [join(nb[i,:], ":","-") for i in 1:size(nb,1)]

    return newpos

end


text:
using Combinatorics
using CSV
using DataFrames
using MySQL

cnx = DBInterface.connect(MySQL.Connection, "localhost", "root", "root", db = "phalp_plos", unix_socket = "/Applications/MAMP/tmp/mysql/mysql.sock")

### retrieve Phyla
data = DBInterface.execute(cnx, "SELECT DISTINCT(lineage_phylum) FROM hosts WHERE lineage_phylum != '';") |> DataFrame
phyla = data[!, 1]

### retrieve Classes
data = DBInterface.execute(cnx, "SELECT DISTINCT(lineage_class) FROM hosts WHERE lineage_class != '';") |> DataFrame
classes = data[!, 1]

### retrieve Orders
data = DBInterface.execute(cnx, "SELECT DISTINCT(lineage_order) FROM hosts WHERE lineage_order != '';") |> DataFrame
orders = data[!, 1]

### retrieve Families
data = DBInterface.execute(cnx, "SELECT DISTINCT(lineage_family) FROM hosts WHERE lineage_family != '';") |> DataFrame
families = data[!, 1]

### retrieve Genera
data = DBInterface.execute(cnx, "SELECT DISTINCT(lineage_genus) FROM hosts WHERE lineage_genus != '';") |> DataFrame
genera = data[!, 1]

### retrieve Species
data = DBInterface.execute(cnx, "SELECT DISTINCT(lineage_species) FROM hosts WHERE lineage_species != '';") |> DataFrame
species = data[!, 1]

### retrieve all architectures
all_architectures = CSV.read("/Users/stefftaelman/Downloads/Documents_local/PROJECTS/PAPER2019/simplified_architectures_condensed.csv", header = false)
endolysin_accs = Vector(CSV.read("/Users/stefftaelman/Downloads/Documents_local/PROJECTS/PAPER2019/75certain_endolysin_accs.csv", header = false).Column1)
endolysin_architectures = all_architectures[in.(all_architectures.Column1, Ref(endolysin_accs)), :]

function get_archs(cnx, host_clade::String)
    if host_clade in phyla
        if host_clade == "Actinobacteria"
            res = input("Do you mean the phylum or the class? (p/c)");
            if res == "p"
                host_string = string(" AND h.lineage_phylum = 'Actinobacteria'")
            elseif res == "c"
                host_string = string(" AND h.lineage_class = 'Actinobacteria'")
            else
                println("Please answer with either 'p' or 'c'.")
            end
        else
            host_string = string(" AND h.lineage_phylum = '", host_clade, "'")
        end
    elseif host_clade in classes
        host_string = string(" AND h.lineage_class = '", host_clade, "'")
    elseif host_clade in orders
        host_string = string(" AND h.lineage_order = '", host_clade, "'")
    elseif host_clade in families
        host_string = string(" AND h.lineage_family = '", host_clade, "'")
    elseif host_clade in genera
        host_string = string(" AND h.lineage_genus = '", host_clade, "'")
    elseif host_clade in species
        host_string = string(" AND h.lineage_species = '", host_clade, "'")
    elseif host_clade == "Cyanophyceae"
        host_string = string("AND h.lineage_phylum = 'Cyanobacteria'")
    elseif host_clade == "all"
        host_string = ""
    else
        println("Please enter a valid host clade to filter on.")
    end
    #=
    if protein_type == "all"
        type_string = ""
    elseif protein_type == "endolysin"
        type_string = "up.type = 'endolysin' AND "
    elseif protein_type == "VAPGH"
        type_string = "up.type = 'VAPGH' AND "
    else
        println("Please enter a valid type to filter on: all, endolysin or VAPGH")
    end
    =#
    ### get accessions
    #query = string("SELECT DISTINCT(up.UniProt_ID) FROM UniProt as up JOIN link_phage_host as l JOIN hosts as h WHERE ", type_string, "up.phages_ID = l.phages_ID AND l.hosts_ID = h.hosts_ID", host_string, ";")
    query = string("SELECT DISTINCT(up.UniProt_ID) FROM UniProt as up JOIN link_phage_host as l JOIN hosts as h WHERE up.phages_ID = l.phages_ID AND l.hosts_ID = h.hosts_ID", host_string, ";")
    data = DBInterface.execute(cnx, query) |> DataFrame
    accs = data[!, :UniProt_ID]

    ### get subsetted dataframe
    archs_df = endolysin_architectures[in(accs).(endolysin_architectures.Column1), :]

    ### get architectures
    arch = Vector{}()
    for i in 1:size(archs_df)[1]
        doms = [k for k in collect(archs_df[i, 2:end]) if !(ismissing(k))]
        if length(doms) > 1
            row = ""
            for (jdx, j) in enumerate(doms)
                row = string(row, j, ";")
                if jdx == length(doms)
                    row = [row[1:end-1]]
                end
            end
        else
            row = doms
        end
        append!(arch, row)
    end
    return arch #.|> a -> Symbol.(split(a, ";"))
end

function get_subset_properties(architectures)
    ### get subset properties
    lens = Vector{Integer}()
    domains = Set{String}()
    for i in architectures
        append!(lens, length(split(i, ";")))
        [push!(domains, j) for j in split(i, ";")]
    end
    modules = collect(domains)
    max_len = maximum(lens)
    #return println("Branch contains architectures composed from $(length(modules)) domains in a maximum of $(max_len) positions.")
    return modules, max_len
end

function symbolize(archs, mod2sym, sym2mod)
    moduledb = Vector{String}()
    for j in archs
        if length(j) == 1
            append!(moduledb, string(j))
        else
            line = ""
            for k in split(j, ";")
                line = line*string(mod2sym[k])
            end
            push!(moduledb, string(line))
        end
    end
    return moduledb
end

function iterate_regex_2_wild(modules, f::Function;
                modsperslot=2,
                verbose=false,
                kwargs...)
    best_score = -Inf
    best_reg = r""
    wildcards = ["", ".{0,1}", ".{0,2}", ".{0,3}"]
    for n1 in 1:modsperslot
        for c1 in combinations(modules, n1)
            for s1 in wildcards
                for n2 in 1:modsperslot
                    for c2 in combinations(modules, n2)
                        reg = Regex("[" * prod(c1) * "]")
                        f_reg = f(reg; kwargs...)
                        if f_reg > best_score
                            best_score = f_reg
                            best_reg = reg
                            verbose && println("$best_reg (score=$best_score)")
                        end
                        reg = Regex("[" * prod(c1) * "]" * s1 * "[" * prod(c2) * "]")
                        f_reg = f(reg; kwargs...)
                        if f_reg > best_score
                            best_score = f_reg
                            best_reg = reg
                            verbose && println("$best_reg (score=$best_score)")
                        end
                    end
                end
            end
        end
    end
    return best_reg, best_score
end

function iterate_regex_3_tame(modules, f::Function;
                modsperslot=2,
                verbose=false,
                kwargs...)
    best_score = -Inf
    best_reg = r""
    for n1 in 1:modsperslot
        for c1 in combinations(modules, n1)
            for n2 in 1:modsperslot
                for c2 in combinations(modules, n2)
                    for m1 in ["", "{0,1}"]
                        for n3 in 1:modsperslot
                            for c3 in combinations(modules, n2)
                                reg = Regex("[" * prod(c1) * "]")
                                f_reg = f(reg; kwargs...)
                                if f_reg > best_score
                                    best_score = f_reg
                                    best_reg = reg
                                    verbose && println("$best_reg (score=$best_score)")
                                end
                                reg = Regex("[" * prod(c1) * "]" * "[" * prod(c2) * "]" * m1)
                                f_reg = f(reg; kwargs...)
                                if f_reg > best_score
                                    best_score = f_reg
                                    best_reg = reg
                                    verbose && println("$best_reg (score=$best_score)")
                                end
                                reg = Regex("[" * prod(c1) * "]" * "[" * prod(c2) * "]" * m1 * "[" * prod(c3) * "]")
                                f_reg = f(reg; kwargs...)
                                if f_reg > best_score
                                    best_score = f_reg
                                    best_reg = reg
                                    verbose && println("$best_reg (score=$best_score)")
                                end
                            end
                        end
                    end
                end
            end
        end
    end
    return best_reg, best_score
end

function iterate_working(modules, f::Function;
                modsperslot=3,
                verbose=false,
                kwargs...)
    best_score = -Inf
    best_reg = r""
    for n1 in 1:modsperslot
        for c1 in combinations(modules, n1)
            for n2 in 1:modsperslot
                for c2 in combinations(modules, n2)
                    for m1 in ["", "{0,1}"]
                        for n3 in 1:modsperslot
                            for c3 in combinations(modules, n2)
                                reg = Regex("[" * prod(c1) * "]")
                                f_reg = f(reg; kwargs...)
                                if f_reg > best_score
                                    best_score = f_reg
                                    best_reg = reg
                                    verbose && println("$best_reg (score=$best_score)")
                                end
                                reg = Regex("[" * prod(c1) * "]" * "[" * prod(c2) * "]" * m1)
                                f_reg = f(reg; kwargs...)
                                if f_reg > best_score
                                    best_score = f_reg
                                    best_reg = reg
                                    verbose && println("$best_reg (score=$best_score)")
                                end
                                reg = Regex("[" * prod(c1) * "]" * "[" * prod(c2) * "]" * m1 * "[" * prod(c3) * "]" * m1)
                                f_reg = f(reg; kwargs...)
                                if f_reg > best_score
                                    best_score = f_reg
                                    best_reg = reg
                                    verbose && println("$best_reg (score=$best_score)")
                                end
                            end
                        end
                    end
                end
            end
        end
    end
    return best_reg, best_score
end

function scoring(regex; db=db, modules=modules, ent_sym=ent_sym, sym2mod=sym2mod)
    true_archs = unique(db) #relevant items
    true_pos = 0
    for i in true_archs
        if occursin(regex, i) == true
            true_pos += length(match(regex, i).match)/length(i)
        end
    end

    ### recall
    recall = true_pos/length(true_archs)

    ### precision
    matches = 0
    for i in ent_sym
        if occursin(regex, i) == true
            matches += length(match(regex, i).match)/length(i)
        end
    end
    precision = true_pos/matches
    F_score = 2*precision*recall/(precision+recall)
    return F_score
end

function desymbolize(regex, sym2mod)
    regex_string = string(regex)[3:end-1]
    dr = ""
    or_criterion = false
    for (idx, i) in enumerate(regex_string)
        if i in keys(sym2mod)
            if regex_string[idx-1] != '{' && regex_string[idx-1] != ','
                dr = dr * sym2mod[i]
                if or_criterion == true && regex_string[idx+1] != ']'
                    dr = dr * "|"
                end
            else
                dr = dr * string(i)
            end
        else
            dr = dr * string(i)
            if i == '['
                or_criterion = true
            elseif i == ']'
                or_criterion = false
            end
        end
    end
    return dr
end

function main_design_exhaustive_iterator(cnx, host_clades, iterator)
    ### get symbols
    entire = unique(get_archs(cnx, "all"))
    all_m, _ = get_subset_properties(entire)
    symbols = String(vcat(UInt8.(65:90), UInt8.(97:122)))
    nmodules = length(all_m)
    mod2sym = Dict{String, Char}()
    sym2mod = Dict{Char, String}()
    for i in 1:nmodules
        mod2sym[all_m[i]] = Char(symbols[i])
        sym2mod[Char(symbols[i])] = all_m[i]
    end
    ent_sym = symbolize(entire, mod2sym, sym2mod)

    for i in host_clades
        ### find rule
        archs = get_archs(cnx, i)
        db = symbolize(archs, mod2sym, sym2mod)
        modules = unique(string(db...))
        regex, score = iterator(modules, scoring, modsperslot=3, verbose=true, db=db, modules=modules, ent_sym=ent_sym, sym2mod=sym2mod)
        rule  = desymbolize(regex, sym2mod)

        ### write to file
        clade_string = ">" * i * "\n"
        open("/Users/stefftaelman/Downloads/Documents_local/PROJECTS/PAPER2019/designs_3pos_working.txt", "a") do io
            write(io, clade_string)
            write(io, (rule*"\n"))
            write(io, (string(score)*"\n"))
            write(io, (string(length(archs))*"\n\n"))
        end
    end
end

#=
list = ["Bacillus cereus", "Bacillus subtilis", "Bacillus thuringiensis", "Listeria monocytogenes", "Staphylococcus aureus", "Enterococcus faecalis",
        "Lactobacillus plantarum", "Lactococcus lactis", "Streptococcus agalactiae", "Streptococcus pneumoniae", "Streptococcus pyogenes",
        "Streptococcus thermophilus"]
=#

list = ["Paenibacillus larvae", "Paenibacillus", "Paenibacillaceae", "Streptococcus dysgalactiae", "Streptococcus suis"]

main_design_exhaustive_iterator(cnx, list, iterate_working) #started 07/12 17:03

b = get_archs(cnx, "Synechococcus")
c = get_archs(cnx, "Synechococcaceae")

b == c

c = get_archs(cnx, "Vibrio")
d = get_archs(cnx, "Vibrionaceae")

c == d

max_stars_repo_name: bjcriel/PhaLP

max_issues_repo_name: bjcriel/PhaLP

max_forks_repo_name: bjcriel/PhaLP


text:
using Test, CUDA, Knet, AutoGrad
using CUDA.CUDNN:
    cudnnDropoutForward,
    cudnnDropoutForward!,
    cudnnDropoutBackward,
    cudnnDropoutSeed,
    cudnnDropoutDescriptor,
        cudnnDropoutDescriptor_t,
        cudnnCreateDropoutDescriptor,
        cudnnSetDropoutDescriptor,
        cudnnGetDropoutDescriptor,
        cudnnRestoreDropoutDescriptor,
        cudnnDestroyDropoutDescriptor,
    cudnnDropoutGetStatesSize,
    cudnnDropoutGetReserveSpaceSize,
    handle

@testset "cudnn/dropout" begin

    N,P = 1000, 0.7
    x = Param(CUDA.rand(N))
    d = cudnnDropoutDescriptor(P)
    cudnnDropoutSeed[] = 1
    @test @gcheck cudnnDropoutForward(x; dropout = P)
    @test @gcheck cudnnDropoutForward(x, d)
    @test @gcheck cudnnDropoutForward!(similar(x), x; dropout = P)
    @test @gcheck cudnnDropoutForward!(similar(x), x, d)
    cudnnDropoutSeed[] = -1

end


text:
using Test
using Clustering

@testset "fuzzy_cmeans()" begin

Random.seed!(34568)

m = 3
n = 1000
k = 5

x = rand(m,n)

@testset "fuzziness = 2.0" begin
    fuzziness = 2.0
    Random.seed!(34568)
    r = fuzzy_cmeans(x, k, fuzziness)
    @test isa(r, FuzzyCMeansResult{Float64})
    @test size(r.centers) == (m,k)
    @test size(r.weights) == (n,k)
    @test sum(r.weights, dims=2) ≈ fill(1.0, n)
    @test all(0 .<= r.weights .<= 1)
end

@testset "fuzziness = 3.0" begin
    fuzziness = 3.0
    Random.seed!(34568)
    r = fuzzy_cmeans(x, k, fuzziness)
    @test isa(r, FuzzyCMeansResult{Float64})
    @test size(r.centers) == (m,k)
    @test size(r.weights) == (n,k)
    @test sum(r.weights, dims=2) ≈ fill(1.0, n)
    @test all(0 .<= r.weights .<= 1)
end

@testset "Abstract data matrix" begin
    fuzziness = 2.0
    Random.seed!(34568)
    r = fuzzy_cmeans(view(x, :, :), k, fuzziness)
    @test isa(r, FuzzyCMeansResult{Float64})
    @test size(r.centers) == (m,k)
    @test size(r.weights) == (n,k)
    @test sum(r.weights, dims=2) ≈ fill(1.0, n)
    @test all(0 .<= r.weights .<= 1)
end

end


text:
nums = parse.(Int, readlines("day10/input.txt"))

push!(nums, 0)
push!(nums, 3+maximum(nums))
sort!(nums)

println(nums)
println(count(i -> (nums[i] - nums[i-1]) == 1, 2:length(nums))*count(i -> (nums[i] - nums[i-1]) == 3, 2:length(nums)))


text:
function TimeStampedPVCoordinates(arg0::AbsoluteDate, arg1::FieldVector3D)
    return TimeStampedPVCoordinates((AbsoluteDate, FieldVector3D), arg0, arg1)
end

function TimeStampedPVCoordinates(arg0::AbsoluteDate, arg1::PVCoordinates)
    return TimeStampedPVCoordinates((AbsoluteDate, PVCoordinates), arg0, arg1)
end

function TimeStampedPVCoordinates(arg0::AbsoluteDate, arg1::PVCoordinates, arg2::PVCoordinates)
    return TimeStampedPVCoordinates((AbsoluteDate, PVCoordinates, PVCoordinates), arg0, arg1, arg2)
end

function TimeStampedPVCoordinates(arg0::AbsoluteDate, arg1::Vector3D, arg2::Vector3D)
    return TimeStampedPVCoordinates((AbsoluteDate, Vector3D, Vector3D), arg0, arg1, arg2)
end

function TimeStampedPVCoordinates(arg0::AbsoluteDate, arg1::Vector3D, arg2::Vector3D, arg3::Vector3D)
    return TimeStampedPVCoordinates((AbsoluteDate, Vector3D, Vector3D, Vector3D), arg0, arg1, arg2, arg3)
end

function TimeStampedPVCoordinates(arg0::AbsoluteDate, arg1::jdouble, arg2::PVCoordinates)
    return TimeStampedPVCoordinates((AbsoluteDate, jdouble, PVCoordinates), arg0, arg1, arg2)
end

function TimeStampedPVCoordinates(arg0::AbsoluteDate, arg1::jdouble, arg2::PVCoordinates, arg3::jdouble, arg4::PVCoordinates)
    return TimeStampedPVCoordinates((AbsoluteDate, jdouble, PVCoordinates, jdouble, PVCoordinates), arg0, arg1, arg2, arg3, arg4)
end

function TimeStampedPVCoordinates(arg0::AbsoluteDate, arg1::jdouble, arg2::PVCoordinates, arg3::jdouble, arg4::PVCoordinates, arg5::jdouble, arg6::PVCoordinates)
    return TimeStampedPVCoordinates((AbsoluteDate, jdouble, PVCoordinates, jdouble, PVCoordinates, jdouble, PVCoordinates), arg0, arg1, arg2, arg3, arg4, arg5, arg6)
end

function TimeStampedPVCoordinates(arg0::AbsoluteDate, arg1::jdouble, arg2::PVCoordinates, arg3::jdouble, arg4::PVCoordinates, arg5::jdouble, arg6::PVCoordinates, arg7::jdouble, arg8::PVCoordinates)
    return TimeStampedPVCoordinates((AbsoluteDate, jdouble, PVCoordinates, jdouble, PVCoordinates, jdouble, PVCoordinates, jdouble, PVCoordinates), arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
end

function shifted_by(obj::TimeStampedPVCoordinates, arg0::jdouble)
    return jcall(obj, "shiftedBy", TimeStampedPVCoordinates, (jdouble,), arg0)
end


text:
global session = nothing
global services = nothing

function get_version()
    majorVersion = Ref{Cint}(0)
    minorVersion = Ref{Cint}(0)
    patchVersion = Ref{Cint}(0)
    buildVersion = Ref{Cint}(0)
    blpapi_getVersionInfo(majorVersion, minorVersion, patchVersion, buildVersion)
    (majorVersion[], minorVersion[], patchVersion[], buildVersion[])
end

function create_session(;host::String="",port::Int=0)
    event_dispatcher = blpapi_EventDispatcher_create(0)
    session_options = blpapi_SessionOptions_create()
    if length(host) > 0
        blpapi_SessionOptions_setServerHost(session_options,host)
    end
    if length(host) > 0
        blpapi_SessionOptions_setServerPort(session_options,port)
    end
    session = blpapi_Session_create(session_options,C_NULL,event_dispatcher,C_NULL)
    blpapi_SessionOptions_destroy(session_options)
    session
end

function open_service(session,name)
    blpapi_Session_openService(session,name)
    service = @with_pointer service blpapi_Session_getService(session,service,name)
    Printf.@printf "SERVICE:   %s\n" blpapi_Service_name(service)
    list_service_operations(service)
    list_service_events(service)
    service
end

function list_service_operations(service)
    for i = 0:(blpapi_Service_numOperations(service)-1)
        oper = @with_pointer oper blpapi_Service_getOperationAt(service,oper,i)
        Printf.@printf "Operation: %s\n" blpapi_Operation_name(oper)
    end
end

function get_name_and_destroy(x)
    name = blpapi_Name_string(x)
    blpapi_Name_destroy(x)
    name
end

function list_service_events(service)
    for i = 0:(blpapi_Service_numEventDefinitions(service)-1)
        event = @with_pointer event blpapi_Service_getEventDefinitionAt(service,event,i)
        Printf.@printf "Event:     %s\n" get_name_and_destroy(blpapi_SchemaElementDefinition_name(event))
    end
end

"Open a Bloomberg API session. The hostname and port can be specified if required."
function bopen(;host::String="",port::Int=0)
    global session
    global services
    if session == nothing
        version = get_version()
        Printf.@printf "BLPAPI DLL version %d.%d.%d.%d\n" version[1] version[2] version[3] version[4]
        services = Dict()
        session = create_session(host=host,port=port)
        blpapi_Session_start(session)
        for name = ["refdata", "apiflds", "instruments", "mktdata", "mktbar", "mktvwap"]
            services[name] = open_service(session,"//blp/"*name)
        end
        retrieve_response(2)
    else
        error("already connected!")
    end
    nothing
end

"Close the current session."
function bclose()
    global session
    global services
    if session == nothing
        error("not connected!")
    else
        blpapi_Session_stop(session)
        # for service = values(services); blpapi_Service_release(service); end
        blpapi_Session_destroy(session)
        services = nothing
        session = nothing
    end
end


text:
"""
    closest_points(p, q, dir; max_iter=100)

Compute the closest points between convex objects `p` and `q` if
they are not colliding. Provide an initial search direction
`dir` in the space of the problem.

Return result of type Tuple with StaticArrays of the two closest
points on each object.

# Examples
```julia-repl
julia> using StaticArrays
julia> p = SMatrix{2,3}([0.0 0.0 1.0; 0.0 2.0 1.0])
julia> q = SMatrix{2,3}([2.0 2.0 3.0; 0.0 2.0 1.0])
julia> dir = SVector{2}(1.0, 0.0)
julia> closest_points(p, q, dir)
([1.0, 1.0], [2.0, 1.0])
```
"""
function closest_points(p::Any, q::Any, init_dir::SVector; max_iter=100)
    collision, psimplex, qsimplex, dir, sz = gjk(p, q, init_dir, max_iter, minimum_distance_cond)

    if !collision
        pclose, qclose = nearestfromsimplex(psimplex, qsimplex, -dir, sz)
        return pclose, qclose
    end
end

"""
    minimum_distance(p, q, dir; max_iter=100)

Compute the minimum seperating distance between convex objects `p` and `q`.
Provide an initial search direction `dir` in the space of the problem.

# Examples
```julia-repl
julia> using StaticArrays
julia> p = SMatrix{2,3}([0.0 0.0 1.0; 0.0 2.0 1.0])
julia> q = SMatrix{2,3}([2.0 2.0 3.0; 0.0 2.0 1.0])
julia> dir = SVector{2}(1.0, 0.0)
julia> minimum_distance(p, q, dir)
1.0
```
"""
function minimum_distance(p::Any, q::Any, init_dir::SVector; max_iter=100)
    collision, psimplex, qsimplex, dir, sz = gjk(p, q, init_dir, max_iter, minimum_distance_cond)
    return collision ? 0.0 : norm(dir)
end

"""
    tolerance_verifcation(p, q, dir, τ; max_iter=100)

Compute if the convex objects `p` and `q` are at least
`τ` tolerance apart. Provide an initial search direction
`dir` in the space of the problem.

# Examples
```julia-repl
julia> using StaticArrays
julia> p = SMatrix{2,3}([0.0 0.0 1.0; 0.0 2.0 1.0])
julia> q = SMatrix{2,3}([2.0 2.0 3.0; 0.0 2.0 1.0])
julia> dir = SVector{2}(1.0, 0.0)
julia> tolerance_verification(p, q, dir, 0.25)
true
```
"""
function tolerance_verification(p::Any, q::Any, init_dir::SVector, τ::Real; max_iter=100)
    collision, = gjk(p, q, init_dir, max_iter, tolerance_verification_cond, τ)
    return !collision
end

"""
    collision_detection(p, q, dir; max_iter=100)

Compute if the convex objects `p` and `q` are colliding.
Provide an initial search direction `dir` in the space
of the problem.

# Examples
```julia-repl
julia> using StaticArrays
julia> p = SMatrix{2,3}([0.0 0.0 1.0; 0.0 2.0 1.0])
julia> q = SMatrix{2,3}([2.0 2.0 3.0; 0.0 2.0 1.0])
julia> dir = SVector{2}(1.0, 0.0)
julia> collision_detection(p, q, dir)
false
```
"""
function collision_detection(p::Any, q::Any, init_dir::SVector{N, T}; max_iter=100) where {N, T}
    collision, = gjk(p, q, init_dir, max_iter, tolerance_verification_cond, eps(T))
    return collision
end

# See Julia issue #28720 for why we have `where {F<:Function}` signature
function gjk(p::Any, q::Any, init_dir::SVector, max_iter::Int, distance::F, params...) where {F<:Function}
    sz = 1
    collision = false
    ps = support(p, init_dir)
    qs = support(q, -init_dir)
    psimplex = insertcolumn(ps)
    qsimplex = insertcolumn(qs)
    dir = qs - ps

    if sum(abs2, dir) ≤ 2*eps(Float64)
        return true, psimplex, qsimplex, dir, sz
    end

    ps = support(p, dir)
    qs = support(q, -dir)
    while check_gjk(psimplex - qsimplex, ps - qs, dir, sz, max_iter, distance, params...)
        sz += 1
        psimplex = insertcolumn(psimplex, ps, sz)
        qsimplex = insertcolumn(qsimplex, qs, sz)
        psimplex, qsimplex, dir, collision, sz = findsimplex(psimplex, qsimplex, sz)
        if collision
            break
        else
            ps = support(p, dir)
            qs = support(q, -dir)
        end

        max_iter -= 1
    end

    return collision, psimplex, qsimplex, dir, sz
end

function check_gjk(simplex::SMatrix, s::SVector, dir::SVector, sz::Int, iter::Int, distance::F, params...) where {F<:Function}
    if iter ≤ 0
        error("GJK failed: maximum number of iterations reached")
    elseif distance(s, dir, params...) || check_degeneracy(simplex, s, sz)
        return false
    else
        return true
    end
end

function minimum_distance_cond(s::SVector, dir::SVector)
    s⋅(-dir) ≥ sum(abs2, dir)
end

function tolerance_verification_cond(s::SVector, dir::SVector, tv::Real)
    s⋅(-dir) ≥ tv^2 || s⋅(-dir) ≥ sum(abs2, dir)
end

@generated function check_degeneracy(simplex::SMatrix{N, M, T}, s::SVector{N, T}, sz::Vararg{Int, 1}) where {N, M, T}
    exprs = :(false)
    for i = 1:M
        exprs = :($i > sz[1] ? $exprs : ($exprs || sum(abs2, simplex[:, $i] - s) ≤ 2*eps($T)))
    end
    return exprs
end


text:
# Indices are periodic
immutable Periodic{I <: Integer} <: Indexing
    dimensions::GridCoords{I}
    strides::GridCoords{I}
end
Periodic{I}(dims::GridCoords{I}) = Periodic{I}(dims, I[strides(zeros(Int8, dims...))...])

function index(kernel::Periodic, indices::GridCoords)
    @assert(size(kernel.dimensions) == size(indices))
    dot(kernel.strides, mod(indices - 1, kernel.dimensions)) + 1
end
function neighbor_index(indexing::Periodic, site::GridCoords, direction::GridCoords)
    @assert length(site) == length(direction)
    index(indexing, site + direction)
end


text:
#############################################################################
#
# Functions for computing the primary radius of the bounding ellipsoid of the
# oscillatory part of the Riemann theta function.
#
# The two subroutines solve for the radius using,
#
# * Theorem 3 of [CRTF] (no derivatives)
# * A generalization of Theorems 5 and 7 of [CRTF] for N derivatives
#
# Original Authors
# -------
# * Chris Swierczewski (@cswiercz) - September 2012, July 2016
# * Grady Williams (@gradyrw) - October 2012
# * Jeremy Upsal (@jupsal) - July 2016
#
# References
# ----------
#
# .. [CRTF] B. Deconinck, M.  Heil, A. Bobenko, M. van Hoeij and M. Schmies,
#    Computing Riemann Theta Functions, Mathematics of Computation, 73, (2004),
#    1417-1442.
#
################################################################################

"""
    radius(ϵ::Float64,
           T::Matrix{Float64},
           derivs::Vector{Vector{Float64}} = Vector{Float64}[],
           accuracy_radius::Float64 = 5.)

Returns the primary radius of the bounding ellipsoid for computing the
Riemann theta function up to accuracy `ϵ`.

The derivative oscillatory part of the Riemann theta function has linear
growth in :math:`z` along the directions of the columns of the Riemann
matrix. `accuracy_radius` is used to determine a radius resulting in an
accurate Riemann theta for all

.. math ::

    ||z|| < \text{accuracy_radius}.

Parameters
----------
- ϵ : Requested accuracy.
- T : A gxg matrix representing the Cholesky decomposition of the imaginary
    part of a Riemann matrix.
- derivs : (Default: []) A list of directional derivatives. The number of
    directional derivatives is the order, N, of the derivative we wish to
    compute.
- accuracy_radius : (Default: 5) Radius for guaranteed region of accuracy. See above.

Returns
-------
- radius : The initial radius of the bounding ellipsoid used to truncate the
    Riemann theta function to desired accuracy.

"""
function radius(ϵ::Float64,
                T::AbstractMatrix{Float64},
                derivs::Vector{Vector{ComplexF64}} = Vector{ComplexF64}[],
                accuracy_radius::Float64 = 5.)
    g = size(T,1)
    # compute the LLL-reduction of T
    U = lll([ T[:,i] for i in 1:size(T,2) ])
    ρ = minimum(norm, U)

    if length(derivs) == 0
        radius0(ϵ, ρ, g)
    else
        radiusN(ϵ, ρ, T, derivs, accuracy_radius)
    end
end

"""
    radius0(eps::Float64, r::Float64, g::Int)::Float64

Compute the radius with no derivatives.
"""
function radius0(ϵ::Float64, ρ::Float64, g::Int)::Float64
    tmp = 2ϵ / g * (ρ / 2.)^g
    tmp = gammainvccdf(g / 2., 1.0, tmp)
    R = sqrt(tmp) + ρ / 2.
    max(R, ( sqrt(2g) + ρ ) / 2)
end

"""
   radiusN(eps, r, T, derivs, accuracy_radius=5)::Float64

Compute the radius with N derivatives.

Parameters
----------
- eps : Requested accuracy.
- r : The length of the shortest lattice vector in the LLL reduction of the
    Cholesky decomposition of the imaginary part of the Riemann matrix.
- T : A gxg matrix representing the Cholesky decomposition of the imaginary
    part of a Riemann matrix.
- derivs : A list of directional derivatives. The number of directional
    derivatives is the order, N, of the derivative we wish to compute.
- accuracy_radius : Radius for guaranteed region of accuracy. See :func:`radius`.

Returns
-------
- radius : The initial radius of the bounding ellipsoid used to truncate the
    Riemann theta function to desired accuracy.

"""
function radiusN(ϵ::Float64, ρ::Float64,
                 T::AbstractMatrix{Float64},
                 derivs::Vector{Vector{ComplexF64}},
                 accuracy_radius::Float64 = 5.)::Float64

    N, g = length(derivs), size(T,1)
    prodnormderiv = prod(norm, derivs)
    normTinv = norm(inv(T))

    lhs = ϵ * ρ ^ g * 2 ^ (1. - g - N) /
          ( π ^ (N / 2) * g * normTinv ^ N * prodnormderiv )

    # define lower bound (guess) and attempt to solve for the radius
    lbnd = (sqrt(g + 2N + sqrt(g^2 + 8N)) + ρ) / 2.
    function rhs(ins::Float64)
        ai(k) = binomial(N,k) * π^(k/2.) *
                (accuracy_radius * normTinv)^k *
                gamma((g+N-k)/2.) *
                gammaccdf((g+N-k)/2., 1.0, ins)
        sum(ai, 0:N) - lhs
    end
    inszero = fzero(rhs, lbnd, 1e5)

    max(sqrt(inszero) + ρ / 2., lbnd)
end


text:
# Example:
# module M
#     using ..Main: @wrapaccessors
#     using MacroTools
#     one = 0
#     two = 0
#     struct Example end
#     Example_get_val(x::Example) = one
#     Example_set_val(x::Example, v) = global one = v
#     println(prettify(@macroexpand @wrapaccessors Example (one, )))
#     @wrapaccessors Example (one, )
# end
# x = Example()
# @assert x.one == M.one == 0
# x.one == 10
# @assert x.one == M.one == 10
macro wrapaccessors(T, fields)
    @assert fields.head === :tuple

    gen_case(i) = :(name === $(QuoteNode(fields.args[i])))
    gen_get(i) = quote
        $(__module__).$(Symbol(T, :_get_, fields.args[i]))(x)
    end
    gen_set(i) = quote
        $(__module__).$(Symbol(T, :_set_, fields.args[i]))(x, value)
    end

    # err_ex = :(error($(Expr(:string, "type $T has no field ", :name))))
    get_ex = Expr(:block, :($Base.getfield(x, name)))
    set_ex = Expr(:block, :($Base.setfield!(x, name, value)))
    for i=2:length(fields.args)
        get_ex = Expr(:elseif, gen_case(i), gen_get(i), get_ex)
        set_ex = Expr(:elseif, gen_case(i), gen_set(i), set_ex)
    end
    get_ex = Expr(:if, gen_case(1), gen_get(1), get_ex)
    set_ex = Expr(:if, gen_case(1), gen_set(1), set_ex)

    ex = quote
        $Base.@inline function $Base.getproperty(x::$(__module__).$(T), name::$Symbol)
            $get_ex
        end
        $Base.@inline function $Base.setproperty!(x::$(__module__).$(T), name::$Symbol, value)
            $set_ex
        end
        $Base.@inline function $Base.propertynames(x::$(__module__).$(T))
            $(Expr(:tuple, map(QuoteNode, fields.args)...))
        end
    end
    esc(ex)
end


text:
function wireframe(scene::Scene, x::AbstractVector, y::AbstractVector, z::AbstractMatrix, attributes::Dict)
    wireframe(ngrid(x, y)..., z, attributes)
end

function wireframe(scene::Scene, x::AbstractMatrix, y::AbstractMatrix, z::AbstractMatrix, attributes::Dict)
    if (length(x) != length(y)) || (length(y) != length(z))
        error("x, y and z must have the same length. Found: $(length(x)), $(length(y)), $(length(z))")
    end
    points = lift_node(to_node(x), to_node(y), to_node(z)) do x, y, z
        Point3f0.(vec(x), vec(y), vec(z))
    end
    NF = (length(z) * 4) - ((size(z, 1) + size(z, 2)) * 2)
    faces = Vector{Int}(NF)
    idx = (i, j) -> sub2ind(size(z), i, j)
    li = 1
    for i = 1:size(z, 1), j = 1:size(z, 2)
        if i < size(z, 1)
            faces[li] = idx(i, j);
            faces[li + 1] = idx(i + 1, j)
            li += 2
        end
        if j < size(z, 2)
            faces[li] = idx(i, j)
            faces[li + 1] = idx(i, j + 1)
            li += 2
        end
    end
    linesegment(scene, view(points, faces), attributes)
end

function wireframe(scene::Scene, mesh, attributes::Dict)
    mesh = to_node(mesh, x-> to_mesh(scene, x))
    points = lift_node(mesh) do g
        decompose(Point3f0, g) # get the point representation of the geometry
    end
    indices = lift_node(mesh) do g
        idx = decompose(Face{2, GLIndex}, g) # get the point representation of the geometry
    end
    linesegment(scene, view(points, indices), attributes)
end