text:
julia> RpcApi.SimpleOrganism[RpcApi.SimpleOrganism(0x0000000000006fb7,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_3(var_2::Int16=-23790)
            o.mem[var_2] = var_2
            o.mem[var_2] = var_2
            var_2 = var_2 / var_2
            return var_2
        end
        local var_1::Int8 = 71
        function func_6(var_4::Int8=-67,var_5::Bool=true)
            local var_8::Bool = false
            if var_4 < var_4
            end
            var_5 = Bool(abs(var_8 - var_8))
            Creature.eatUp(c,o,Int(var_4))
            Creature.eatDown(c,o,Int(var_4))
            return var_4
        end
        Creature.eatUp(c,o,Int(var_1))
        if var_1 < var_1
            Creature.stepUp(o)
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        var_1 = var_1 + var_1
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,156319,0x0000004e,Dict{Int16,Int16}(),[210,158],18),RpcApi.SimpleOrganism(0x0000000000006327,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,151961,0x00000025,Dict{Int16,Int16}(),[173,23],7),RpcApi.SimpleOrganism(0x0000000000006c85,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_14(var_12::Int64=-1172685063416274102,var_13::String="6CAs70G3")
            return var_12
        end
        local var_8::Int64 = 7733858157021421351
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            Creature.stepRight(o)
            Creature.stepUp(o)
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepLeft(o)
            o.mem[var_2] = var_2
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,143251,0x00000050,Dict{Int16,Int16}(),[56,102],18),RpcApi.SimpleOrganism(0x0000000000007071,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_3(var_2::Int16=-23790)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,136535,0x00000006,Dict{Int16,Int16}(),[224,167],10),RpcApi.SimpleOrganism(0x00000000000060cb,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_10::Int16 = 30832
        function func_8(var_7::Int8=15)
            Creature.stepRight(o)
            Creature.stepRight(o)
            Creature.eatUp(c,o,Int(var_7))
            return var_7
        end
        function func_3(var_2::Int16=-23790)
            local var_11::Int16 = 19127
            Creature.stepRight(o)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,129080,0x00000050,Dict(30832=>30832),[139,23],17),RpcApi.SimpleOrganism(0x0000000000006867,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_8(var_7::Int8=15)
            for i::Int8 = 1:div(var_7,_LOOP_STEPS_DIVIDER)
            end
            return var_7
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,128290,0x00000042,Dict{Int16,Int16}(),[145,24],7),RpcApi.SimpleOrganism(0x0000000000006893,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,122596,0x00000025,Dict{Int16,Int16}(),[171,27],7),RpcApi.SimpleOrganism(0x000000000000639c,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_10::Int16 = -17526
        function func_3(var_2::Int16=-23790)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,121367,0x00000007,Dict{Int16,Int16}(),[222,167],11),RpcApi.SimpleOrganism(0x0000000000006a17,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_14(var_12::Int64=-1172685063416274102,var_13::String="6CAs70G3")
            return var_12
        end
        local var_8::Int64 = 7733858157021421351
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            Creature.stepRight(o)
            Creature.stepLeft(o)
            Creature.stepRight(o)
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepLeft(o)
            Creature.stepLeft(o)
            o.mem[var_2] = var_2
            if var_2 > var_2
            end
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,120048,0x00000050,Dict{Int16,Int16}(),[56,102],21),RpcApi.SimpleOrganism(0x00000000000070eb,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        function func_12(var_10::Bool=false,var_11::Int16=-5540)
            Creature.stepUp(o)
            Creature.stepRight(o)
            Creature.stepRight(o)
            return var_10
        end
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,480,1,110904,0x00000057,Dict{Int16,Int16}(),[82,200],8),RpcApi.SimpleOrganism(0x0000000000006a13,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,110245,0x00000025,Dict{Int16,Int16}(),[174,28],7),RpcApi.SimpleOrganism(0x00000000000071bc,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_8::Int64 = -333518551926540339
        function func_3(var_2::Int16=-23790)
            Creature.stepDown(o)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        if var_1 !== var_1
        end
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        var_1 = var_1 * var_1
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,109662,0x00000054,Dict{Int16,Int16}(),[53,20],11),RpcApi.SimpleOrganism(0x00000000000070ea,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_12::Bool = false
        function func_9(var_7::Bool=true,var_8::Int64=-2995420336708105682)
            return var_7
        end
        local var_1::Int8 = 71
        function func_11(var_10::Int64=-3612233205782250359)
            local var_13::String = "xkcX4A7L"
            return var_10
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        Creature.stepRight(o)
        return true
    end),[110,300,98,0,1,1,1],0,758,1,101690,0x00000048,Dict{Int16,Int16}(),[194,63],12),RpcApi.SimpleOrganism(0x0000000000007148,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        function func_6(var_4::Int8=-67,var_5::Bool=true)
            Creature.eatUp(c,o,Int(var_4))
            Creature.eatLeft(c,o,Int(var_4))
            Creature.eatUp(c,o,Int(var_4))
            return var_4
        end
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,99237,0x0000004b,Dict{Int16,Int16}(),[76,154],7),RpcApi.SimpleOrganism(0x0000000000006db6,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_14(var_12::Int64=-1172685063416274102,var_13::String="6CAs70G3")
            return var_12
        end
        local var_8::Int64 = 7733858157021421351
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            Creature.stepRight(o)
            Creature.stepUp(o)
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepLeft(o)
            Creature.stepRight(o)
            o.mem[var_2] = var_2
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,99116,0x00000053,Dict{Int16,Int16}(),[57,102],20),RpcApi.SimpleOrganism(0x00000000000065cf,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_3(var_2::Int16=-23790)
            var_2 = if haskey(o.mem,var_2)
                    o.mem[var_2]
                else
                    var_2
                end
            var_2 = var_2 - var_2
            Creature.stepUp(o)
            return var_2
        end
        local var_1::Int8 = 71
        if var_1 < var_1
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            local var_4::Int64 = -5300375428537857768
            Creature.stepUp(o)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepLeft(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,99050,0x00000020,Dict{Int16,Int16}(),[123,161],14),RpcApi.SimpleOrganism(0x000000000000654e,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,95758,0x00000025,Dict{Int16,Int16}(),[169,26],7),RpcApi.SimpleOrganism(0x0000000000006fdc,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,95138,0x00000025,Dict{Int16,Int16}(),[169,27],7),RpcApi.SimpleOrganism(0x0000000000006eae,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,93971,0x00000025,Dict{Int16,Int16}(),[174,26],7),RpcApi.SimpleOrganism(0x0000000000006808,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,93249,0x00000025,Dict{Int16,Int16}(),[169,27],7),RpcApi.SimpleOrganism(0x000000000000703a,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_8::Int16=25845,var_9::Bool=true)
            local var_11::String = "x5v2yl9K"
            Creature.stepLeft(o)
            if var_8 !== var_8
            end
            Creature.stepLeft(o)
            var_9 = var_9 | var_9
            return var_8
        end
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            Creature.stepDown(o)
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.stepDown(o)
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,92618,0x00000047,Dict{Int16,Int16}(),[96,39],18),RpcApi.SimpleOrganism(0x00000000000060d3,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,89798,0x00000025,Dict{Int16,Int16}(),[169,25],7),RpcApi.SimpleOrganism(0x0000000000007192,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,87099,0x00000025,Dict{Int16,Int16}(),[175,28],7),RpcApi.SimpleOrganism(0x0000000000006c7c,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_10::Int8 = 102
        function func_3(var_2::Int16=-23790)
            local var_11::Bool = false
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,85927,0x00000004,Dict{Int16,Int16}(),[224,167],12),RpcApi.SimpleOrganism(0x00000000000070dd,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_8(var_7::Int8=15)
            Creature.stepDown(o)
            return var_7
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,82094,0x00000000,Dict{Int16,Int16}(),[154,26],8),RpcApi.SimpleOrganism(0x0000000000006c36,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        function func_13(var_12::Bool=false)
            Creature.stepDown(o)
            return var_12
        end
        Creature.eatLeft(c,o,Int(var_1))
        Creature.stepUp(o)
        Creature.eatUp(c,o,Int(var_1))
        var_1 = var_1 * var_1
        Creature.eatDown(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,80618,0x00000044,Dict{Int16,Int16}(),[240,134],8),RpcApi.SimpleOrganism(0x0000000000006ef4,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_3(var_2::Int16=-23790)
            Creature.stepDown(o)
            var_2 = if haskey(o.mem,var_2)
                    o.mem[var_2]
                else
                    var_2
                end
            return var_2
        end
        local var_1::Int8 = 71
        function func_6(var_4::Int8=-67,var_5::Bool=true)
            local var_9::Bool = true
            return var_4
        end
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        if var_1 < var_1
            local var_10::Bool = false
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        var_1 = var_1 + var_1
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,79556,0x00000000,Dict{Int16,Int16}(),[154,156],13),RpcApi.SimpleOrganism(0x0000000000006232,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,79546,0x00000025,Dict{Int16,Int16}(),[169,25],7),RpcApi.SimpleOrganism(0x0000000000006fe0,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_6(var_5::Bool=true)
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            var_2 = if haskey(o.mem,var_2)
                    o.mem[var_2]
                else
                    var_2
                end
            var_2 = var_2 - var_2
            Creature.stepUp(o)
            return var_2
        end
        local var_1::Int8 = 71
        if var_1 < var_1
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            local var_4::Int64 = -5300375428537857768
            Creature.stepUp(o)
        end
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepLeft(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,77835,0x00000021,Dict{Int16,Int16}(),[124,161],15),RpcApi.SimpleOrganism(0x00000000000070b6,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_3(var_2::Int16=-23790)
            o.mem[var_2] = var_2
            o.mem[var_2] = var_2
            var_2 = var_2 / var_2
            return var_2
        end
        local var_1::Int8 = 71
        function func_6(var_4::Int8=-67,var_5::Bool=true)
            local var_8::Bool = false
            if var_4 < var_4
            end
            var_5 = Bool(abs(var_8 - var_8))
            Creature.eatUp(c,o,Int(var_4))
            Creature.stepDown(o)
            return var_4
        end
        Creature.eatUp(c,o,Int(var_1))
        if var_1 < var_1
            Creature.stepUp(o)
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        var_1 = var_1 + var_1
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,77300,0x0000004d,Dict{Int16,Int16}(),[210,159],18),RpcApi.SimpleOrganism(0x0000000000006f14,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,76621,0x00000025,Dict{Int16,Int16}(),[169,27],7),RpcApi.SimpleOrganism(0x00000000000070d3,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,75042,0x00000025,Dict{Int16,Int16}(),[169,27],7),RpcApi.SimpleOrganism(0x0000000000006af8,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,73734,0x00000025,Dict{Int16,Int16}(),[169,27],7),RpcApi.SimpleOrganism(0x0000000000006e94,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_11(var_10::String="RHe1aCCS")
            return var_10
        end
        function func_7(var_6::Int8=82)
            local var_8::Int16 = -14590
            return var_6
        end
        function func_3(var_2::Int16=-23790)
            local var_5::String = "Ay0IrEpK"
            local var_4::Int64 = -3735695767625807121
            var_5 = var_5[1:if length(var_5) > length(var_5)
                            0
                        else
                            length(var_5) - length(var_5)
                        end]
            Creature.stepLeft(o)
            if var_4 < var_4
            end
            Creature.stepUp(o)
            Creature.stepDown(o)
            return var_2
        end
        local var_1::Int8 = 71
        local var_9::String = "KoM81Kti"
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        if var_1 !== var_1
        end
        Creature.eatLeft(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,934,1,73111,0x00000051,Dict{Int16,Int16}(),[213,31],19),RpcApi.SimpleOrganism(0x00000000000070ce,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_8(var_7::Int8=15)
            Creature.stepDown(o)
            Creature.eatDown(c,o,Int(var_7))
            return var_7
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,72511,0x00000045,Dict{Int16,Int16}(),[152,27],10),RpcApi.SimpleOrganism(0x0000000000006f8d,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_8(var_7::Int8=15)
            Creature.stepDown(o)
            return var_7
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,72036,0x00000044,Dict{Int16,Int16}(),[151,26],9),RpcApi.SimpleOrganism(0x000000000000716d,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        function func_6(var_4::Int8=-67,var_5::Bool=true)
            Creature.stepLeft(o)
            Creature.eatUp(c,o,Int(var_4))
            Creature.eatLeft(c,o,Int(var_4))
            Creature.eatUp(c,o,Int(var_4))
            return var_4
        end
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,70981,0x0000004c,Dict{Int16,Int16}(),[75,155],8),RpcApi.SimpleOrganism(0x00000000000067e0,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_3(var_2::Int16=-23790)
            if var_2 == var_2
            end
            return var_2
        end
        local var_1::Int8 = 71
        function func_6(var_4::Int8=-67,var_5::Bool=true)
            Creature.stepUp(o)
            return var_4
        end
        Creature.eatUp(c,o,Int(var_1))
        if var_1 < var_1
        end
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        var_1 = var_1 + var_1
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,70927,0x00000051,Dict{Int16,Int16}(),[212,30],10),RpcApi.SimpleOrganism(0x0000000000006e9e,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,69139,0x00000025,Dict{Int16,Int16}(),[175,26],7),RpcApi.SimpleOrganism(0x0000000000006aea,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,68838,0x00000025,Dict{Int16,Int16}(),[168,27],7),RpcApi.SimpleOrganism(0x00000000000070b2,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_3(var_2::Int16=-23790)
            o.mem[var_2] = var_2
            var_2 = var_2 / var_2
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        if var_1 < var_1
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        var_1 = var_1 + var_1
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,68056,0x00000000,Dict{Int16,Int16}(),[208,159],10),RpcApi.SimpleOrganism(0x00000000000071c9,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_10(var_8::Int16=25845,var_9::Bool=true)
            var_8 = var_8 * var_8
            return var_8
        end
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            Creature.stepUp(o)
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            var_2 = var_2 - var_2
            Creature.stepRight(o)
            Creature.stepUp(o)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.stepRight(o)
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,66537,0x0000004e,Dict{Int16,Int16}(),[8,86],13),RpcApi.SimpleOrganism(0x0000000000006f40,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_22(var_20::Int16=15670,var_21::Int64=-7138872300519295142)
            return var_20
        end
        function func_17(var_16::Int8=-123)
            Creature.stepUp(o)
            return var_16
        end
        local var_2::Int8 = 110
        local var_1::Int8 = 71
        function func_8(var_6::Int16=-11856,var_7::String="pNFy7t2v")
            local var_23::Int8 = -103
            Creature.stepRight(o)
            var_6 = var_6 / var_6
            if var_6 === var_6
            end
            for i::Int8 = 1:div(var_23,_LOOP_STEPS_DIVIDER)
            end
            return var_6
        end
        Creature.eatLeft(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        var_2 = var_2 + var_1
        Creature.stepDown(o)
        Creature.eatLeft(c,o,Int(var_2))
        Creature.eatLeft(c,o,Int(var_2))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            local var_19::Int16 = -8980
            local var_24::String = "gehm8kFd"
            local var_25::Int64 = -7950673259632230904
            Creature.stepUp(o)
            Creature.stepLeft(o)
        end
        return true
    end),[110,300,98,0,1,1,1],21,1000,1,65170,0x000000e8,Dict{Int16,Int16}(),[85,12],23),RpcApi.SimpleOrganism(0x0000000000006486,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_8::Int64 = 7733858157021421351
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            local var_12::Int64 = -5381659936818944240
            return var_5
        end
        function func_3(var_2::Int16=-23790)
            Creature.stepUp(o)
            Creature.stepRight(o)
            return var_2
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],47,1000,1,64829,0x0000005e,Dict{Int16,Int16}(),[55,102],14),RpcApi.SimpleOrganism(0x00000000000065e4,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_8(var_7::Int8=15)
            var_7 = var_7 - var_7
            return var_7
        end
        local var_1::Int8 = 71
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        var_1 = var_1 / var_1
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,64065,0x0000003f,Dict{Int16,Int16}(),[142,29],10),RpcApi.SimpleOrganism(0x0000000000006aeb,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_12(var_10::Int8=-68,var_11::String="p6AIcFXF")
            return var_10
        end
        local var_8::Int64 = 7733858157021421351
        function func_7(var_5::Int64=-733666207646247602,var_6::String="dFC3ewdY")
            Creature.stepLeft(o)
            return var_5
        end
        local var_1::Int8 = 71
        if var_8 != var_8
            Creature.stepRight(o)
        end
        if var_1 !== var_1
            local var_14::String = "tRpm42Wl"
            Creature.stepRight(o)
            Creature.stepRight(o)
            var_14 = var_14 * var_14
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.stepDown(o)
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,62511,0x0000005b,Dict{Int16,Int16}(),[101,14],18),RpcApi.SimpleOrganism(0x00000000000070ba,:(function (c::Config.ConfigData,o::Creature.Organism)
        function func_3(var_2::Int16=-23790)
            o.mem[var_2] = var_2
            o.mem[var_2] = var_2
            var_2 = var_2 / var_2
            return var_2
        end
        local var_1::Int8 = 71
        function func_6(var_4::Int8=-67,var_5::Bool=true)
            local var_8::Bool = false
            if var_4 < var_4
            end
            var_5 = Bool(abs(var_8 - var_8))
            Creature.eatUp(c,o,Int(var_4))
            Creature.stepDown(o)
            return var_4
        end
        Creature.eatUp(c,o,Int(var_1))
        if var_1 < var_1
            Creature.stepUp(o)
        end
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatRight(c,o,Int(var_1))
        Creature.eatLeft(c,o,Int(var_1))
        var_1 = var_1 + var_1
        return true
    end),[110,300,98,0,1,1,1],0,1000,1,61311,0x0000004d,Dict{Int16,Int16}(),[211,158],18),RpcApi.SimpleOrganism(0x0000000000006abf,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,59749,0x00000025,Dict{Int16,Int16}(),[169,27],7),RpcApi.SimpleOrganism(0x000000000000703b,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,59327,0x00000025,Dict{Int16,Int16}(),[169,27],7),RpcApi.SimpleOrganism(0x0000000000006c58,:(function (c::Config.ConfigData,o::Creature.Organism)
        local var_1::Int8 = 71
        Creature.eatUp(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatDown(c,o,Int(var_1))
        Creature.eatUp(c,o,Int(var_1))
        for i::Int8 = 1:div(var_1,_LOOP_STEPS_DIVIDER)
            Creature.stepRight(o)
        end
        return true
    end),[110,300,98,0,1,1,1],0,1000,0,59275,0x00000025,Dict{Int16,Int16}(),[169,26],7)]

max_stars_repo_name: tmptrash/jevo

max_issues_repo_name: tmptrash/jevo

max_forks_repo_name: tmptrash/jevo


text:
####################################################

#  Implementing PRM and functions for plotting PRM
#  Parameters incude num samples, connection distance, a list of obstacles, and start and goal states
#  Graph search implemented is Astar. Edge cost is assumed to be equal to euclidean distance.
#  To use, call ` include("PRM.jl") ` from any Julia file in the same folder.
#  nouyang 2017

####################################################

using Plots
using DataStructures
using GeometryTypes
using Distributions

module algT
    using GeometryTypes
    # export GraphNode, Edge, Obstacle, Room
    # struct PointAlg
        # x::Int64
        # y::Int64

    struct GraphNode
        id::Int64
        state::Point{2, Float64}
    end

    struct Edge
        startID::Int64
        endID::Int64
        #edge::LineSegment(Point{2, Float64}, Point{2, Float64})
        #edge::LineSegment{}
    end

    struct Obstacle
        id::Int64
        rect::HyperRectangle{2, Vec}
        #color
        #fillalpha
    end

    struct Room
        width::Int64
        height::Int64
        walls::Vector{LineSegment}
        #walls::HyperRectangle
        obstacles::Vector{HyperRectangle}
    end

    struct AlgParameters
        #startGoal::Point{2, Float64}
        #endGoal::Point{2, Float64}
        numSamples::Int64
        connectRadius::Int64
        # goal region?? should be rectangle? aka error from goal allowed
    end

    struct queueTmp
        #pt::Point{2, Float64}
        node::algT.GraphNode
        statesList::Vector{algT.GraphNode}
        cost::Int64
    end

    struct roadmap
        startstate::Point{2,Float64}
        goalstate::Point{2,Float64}
        nodeslist::Vector{GraphNode}
        edgeslist::Vector{Edge}
    end

    #Base.show(io::IO, v::Vertex) =# #print(io, "V($(v.id), ($(v.state.x),$(v.state.y)))")
    #Base.show(io::IO, p::Point) =# #print(io, "P($(p.x),$(p.y))")
    #Base.show(io::IO, q::tempQueueType) =# #print(io, "Q($(q.v),$(q.statesList) $(q.cost))")
    Base.isless(q1::queueTmp, q2::queueTmp) = q1.cost < q2.cost
    #Base.isless(p1::Point, p2::Point) = q1.x< q2.x
    #Base.isless(p1::Point, p2::Point) = q1[1] < q2[1]

end

module algfxn
    using GeometryTypes
    using algT

	function ccw(A,B,C)
        # determines direction of lines formed by three points
        return (C[2]-A[2]) * (B[1]-A[1]) > (B[2]-A[2]) * (C[1]-A[1])
    end

    function intersects(line1, line2) #no ":" at the end!
        A, B = line1[1], line1[2]
        C, D = line2[1], line2[2]
        return ( (ccw(A, C, D) != ccw(B, C, D)) && ccw(A, B, C) != ccw(A, B, D))
    end

    function decompRect(r::HyperRectangle) #GeometryTypes.HyperRectangle{2,Float64}
        corners = decompose(Point{2, Float64}, r)
        corners = [Point(pt) for pt in corners]
        lineBottom  = LineSegment(corners[1], corners[2])
        lineTop     = LineSegment(corners[3], corners[4])
        lineLeft    = LineSegment(corners[1], corners[3])
        lineRight   = LineSegment(corners[2], corners[4])
        lines = Vector{LineSegment}()
        push!(lines, lineTop, lineRight, lineBottom, lineLeft)
        return lines
    end

    #function isCollidingNode(node::algT.GraphNode, obsList::Vector{algT.Obstacle}
    function isCollidingNode(node::Point{2, Float64}, obsList::Vector{HyperRectangle})
        for obs in obsList
            if contains(obs, node)
                return true
            end
        end
        return false
    end

    function isCollidingObstacles(line::LineSegment, obsList::Vector{HyperRectangle})
        for obs in obsList
            rectLines = decompRect(obs)
            for rectline in rectLines
                if intersects(line, rectline)[1]
                    return true
                end
            end
        end
        return false
    end

    function isCollidingWalls(line::LineSegment, walls::Vector{LineSegment})
        for wall in walls
            if intersects(line, wall)
                return true
            end
        end
        return false
    end

    function findNearestNodes(nodestate, nodeslist, maxDist)
        # given maxDist, return all nodes within that distance of node
        nearestNodes = Vector{Tuple{algT.GraphNode, Float64}}()
        for n in nodeslist
            dist = min_euclidean(Vec(nodestate), Vec(n.state))
            if dist < maxDist
                push!(nearestNodes, (n, dist))
            end
        end
        # return list sorted by distance?
        # or just return list with distances included for now...
        return nearestNodes
    end

    function costPath(solPath)
        pathcost = 0
        for i in 2:length(solPath)
            curN  = solPath[i].state
            prevN = solPath[i-1].state
            pathcost += min_euclidean(Vec(curN), Vec(prevN))
        end
        return pathcost
    end

    function findNode(nodeID, nodeslist)
        #since we haven't removed any nodes, nodeslist should be sorted by index. but just in case, let's search through it
        index = findfirst([node.id for node in nodeslist], nodeID)
        return nodeslist[index]
    end

end

module plotfxn

    using GeometryTypes
    using Plots
    using algfxn
    using algT

    ###  Plots.jl recipes

    @recipe function f(r::HyperRectangle)
        points = decompose(Point{2,Float64}, r)
        rectpoints = points[[1,2,4,3],:]
        xs = [pt[1] for pt in rectpoints];
        ys = [pt[2] for pt in rectpoints];
        seriestype := :shape
        color = :orange
        #m = (:black, stroke(0))
        s = Shape(xs[:], ys[:])
    end

    @recipe function f(pt::Point)
        xs = [pt[1]]
        ys = [pt[2]]
        seriestype --> :scatter
        color = :orange
        markersize := 3
        xs, ys
    end

    @recipe function f(l::LineSegment)
        xs = [ l[1][1], l[2][1] ]
        ys = [ l[1][2], l[2][2] ]
        # seriestype = :line
        color = :red
        lw := 3
        xs, ys
    end

    @recipe function f(rectList::Vector{<:HyperRectangle})
        for r in rectList
            @series begin
                r
            end
        end
    end

    @recipe function f(ptList::Vector{<:Point})
        for p in ptList
            @series begin
                p
            end
        end
    end

    @recipe function f(lineList::Vector{<:LineSegment})
        for l in lineList
            @series begin
                l
            end
        end

    end

    ####

    function plotRoom(room)
        aPlot = plot() #Todo! this assumes plotroom is first thing called()
        roomWidth, roomHeight, walls, obstacles = room.width, room.height, room.walls, room.obstacles
       # #print("\nPlotting Room\n")
        plot!(aPlot, walls, color =:black)
        plot!(aPlot, obstacles, fillalpha=0.5)
        return aPlot
    end

    function plotPRM(roomPlot, roadmap, solPath, title)
        startstate, goalstate, nodeslist, edgeslist = roadmap.startstate, roadmap.goalstate, roadmap.nodeslist, roadmap.edgeslist

        x = [n.state[1] for n in nodeslist]
        y = [n.state[2] for n in nodeslist]
        scatter!(roomPlot, x,y, color=:black)

        edgeXs, edgeYs = [], []
        for e in edgeslist
            startN = algfxn.findNode(e.startID, nodeslist)
            endN = algfxn.findNode(e.endID, nodeslist)
            x1,y1 = startN.state[1], startN.state[2]
            x2,y2 = endN.state[1], endN.state[2]
            push!(edgeXs, x1, x2, NaN) #the NaNs, keep spaces between edges correctly unplotted
            push!(edgeYs, y1, y2, NaN)
        end

        plot!(roomPlot, edgeXs, edgeYs, color=:tan, linewidth=0.3)

        # plot solution
        prmPlot = plotSolPath(roomPlot, solPath)

        #title!(prmPlot, title, titlefont = afont)
        title!(prmPlot, title)
        plot!(prmPlot, legend=false, size=(600,600), xaxis=((-5,25), 0:1:20 ),
              yaxis=((-5,25), 0:1:20), foreground_color_grid= :black)
        return prmPlot
    end

    function plotSolPath(aPlot, solPath)
        print("\n ---Solution Path----- \n")
        #@show solPath
        print("\n -------- \n")
        if solPath != Void
            xPath = [n.state[1] for n in solPath]
            yPath = [n.state[2] for n in solPath]
            xstart, ystart = solPath[1].state
            xend, yend = solPath[end].state
            # plot start pt
            scatter!(aPlot, [xstart], [ystart],
                     markercolor= :red, markershape = :circle,  markersize = 6, markerstrokealpha = 0.5, markerstrokewidth=1)
            # plot goal pt
            scatter!(aPlot, [xend], [yend],
                     markerstrokecolor = :green, markershape = :star,  markersize = 5, markerstrokealpha = 1, markerstrokewidth=5)

            # plot path
            plot!(aPlot, xPath, yPath, color = :orchid, linewidth=3, fillalpha = 0.3)
        else
           # #print("\n --- No solution path found ----- \n")
        end
        return aPlot
    end

end

function preprocessPRM(room, parameters)
    roomWidth, roomHeight, walls, obstacles = room.width, room.height, room.walls, room.obstacles
    numPts, connectRadius = parameters.numSamples, parameters.connectRadius

    nodeslist = Vector{algT.GraphNode}()
    edgeslist = Vector{algT.Edge}()

    currID = 1

    # Sample points, create list of nodes
    for i in 1:numPts
        xrand, yrand = rand(Uniform(0, roomWidth), 2)
		#xrand,yrand = rand(1.0:roomWidth-1,2)
        n = Point(xrand, yrand) #new point in room
        if !algfxn.isCollidingNode(n, obstacles) #should write fxn to check for sampling *on* a wall at some point TODO
            newNode = algT.GraphNode(currID, n)
            currID += 1
            push!(nodeslist, newNode)

        else
            #print("\n NODE REMOVED: $n \n")
        end
    end

    # Connect each node to its neighboring nodes within a ball or radius r, creating edges
    for startnode in nodeslist
        neighbors = [item[1] for item in algfxn.findNearestNodes(startnode.state, nodeslist, connectRadius)] # parent point
        n = [algfxn.findNearestNodes(startnode.state, nodeslist, connectRadius)] # parent point
        for endnode in neighbors
            candidateEdge = LineSegment(startnode.state, endnode.state)
            if !algfxn.isCollidingObstacles(candidateEdge, obstacles) & !algfxn.isCollidingWalls(candidateEdge, walls)
                #line = LineSegment(startnode.state, endnode.state)
                newEdge = algT.Edge(startnode.id, endnode.id) #by ID, or just store node? #wait no, i'd have multiple copies of same node for no real reason, mulitple edges per node
                push!(edgeslist, newEdge)
            else
                #print("\n EDGE REMOVED: $startnode WITH $endnode  \n")
            end
        end
    end

    #@show edgeslist
    #@printf("\nPath found? %s Length of nodeslist: %d\n", isPathFound, length(nodeslist))
    return nodeslist, edgeslist
end

function getSuccessors(curNode, edgeslist, nodeslist) #assuming bidirectional for now
    #Find all edges that start or end at current node, and then make a list of the corresponding start or end nodes
    nodeID = curNode.id
    successorNodeIDs = Vector{Int}()
    successors = Vector{algT.GraphNode}()

    for e in edgeslist
        if e.startID == nodeID
            push!(successorNodeIDs, e.endID)
        end
        if e.endID == nodeID #should I include endID? it is bidirectional after all.
            push!(successorNodeIDs,  e.startID) #yes, because local planner connects in bidirectional way
        end
    end

    for id in successorNodeIDs
        node = algfxn.findNode(id, nodeslist)
        push!(successors, node)
    end

    return successors
end

function queryPRM(startstate, goalstate, nodeslist, edgeslist, obstaclesList)
    # to find nearest node, set connect radius to be infinity for now #todo
    connectRadius = 99;
    n_nearStart= algfxn.findNearestNodes(startstate, nodeslist, connectRadius) #Get distance from start, for all points in graph.
    n_nearGoal= algfxn.findNearestNodes(goalstate, nodeslist, connectRadius)

    ## SECTION remove nodes that we cannot reach in a straight line without going through an obstacle
    #todo: this is expensive, we should only check distances in order

    # n_nearStart is tuple of node and distance
    sort!(n_nearStart, by=n_nearStart->n_nearStart[2]) #Sort by distance and pick node with smallest distance from start
    sort!(n_nearGoal, by=n_nearGoal->n_nearGoal[2])
    #print("\n ----------------- \n")
    #@show n_nearStart
    #print("\n ----------------- \n")
    #@show n_nearGoal

    nodestart = algT.GraphNode(9999,Point(9999,9999))
    nodegoal = algT.GraphNode(9999,Point(9999,9999))

    for (n, dist) in n_nearStart
        # bar = typeof(startstate)
        # bar2 = typeof(n)
        ## #print("\n$bar, $bar2\n")
        candidateline = LineSegment(Point(startstate), Point(n.state))
        if !algfxn.isCollidingObstacles(candidateline, obstaclesList)
            nodestart = n
            break
        end
    end

    for (n, dist) in n_nearGoal
        candidateline = LineSegment(Point(goalstate), n.state)
        if !algfxn.isCollidingObstacles(candidateline, obstaclesList)
            nodegoal = n
            break
        end
    end

    if nodestart == algT.GraphNode(9999,Point(9999,9999))
        nodestart = algT.GraphNode(0, Point(0,0))
        #print("ahhhhhh didn't find a start node")
    end
    if nodegoal == algT.GraphNode(9999,Point(9999,9999))
        nodegoal = algT.GraphNode(0, Point(0,0))
       # #print("ahhhhhh didn't find a goal node")
    end

    ## SECTION END

   # #print("This is the beginState $(startstate) and the endState $(goalstate)\n")
   # #print("This is the beginVertex--> $(nodestart) >>> and the endVertex--> $(nodegoal)\n")

    pathNodes = Vector{algT.GraphNode}()
    visited = Vector{algT.GraphNode}() #nodes we've searched through

    frontier = PriorityQueue()
    queue1 = algT.queueTmp(nodestart, pathNodes, 1)
    enqueue!(frontier, queue1, 1) #root node has cost 0
    pathcost = 99999

    #################### A star search
    while length(frontier) != 0
        front = DataStructures.dequeue!(frontier)
        pathVertices = []

        curNode, pathNodes, totalEdgeCost = front.node, front.statesList, front.cost

        if curNode == nodegoal
           # #print("Hurrah! endState reached! \n")
            unshift!(pathNodes, nodestart) #prepend our first path node back to pathVertices
            unshift!(pathNodes, algT.GraphNode(0, startstate)) #prepend the start
            push!(pathNodes, algT.GraphNode(0, goalstate)) #append the goal
            finalPathCost = algfxn.costPath(pathNodes) #Assuming edge cost is Euclidean cost
            isPathFound = true
            return (finalPathCost, isPathFound, pathNodes) #list of nodes in solution path

        else
            if !(curNode in visited)
                push!(visited, curNode) # Add all successors to the stack

                for candidateNode in getSuccessors(curNode, edgeslist, nodeslist)
                    newEdgeCost = min_euclidean(Vec(curNode.state),
                                                Vec(candidateNode.state))
                    #edgecost is euclidean dist(state,state). better to pass
                   # Node than to perform node lookup everytime (vs passing id)
                    f_x = totalEdgeCost + newEdgeCost + min_euclidean(Vec(candidateNode.state), Vec(nodegoal.state)) #heuristic = euclidean distance to end goal
                    p = deepcopy(pathNodes)
                    push!(p, candidateNode)
                    if !(candidateNode in keys(frontier))
                        newQ = algT.queueTmp(candidateNode, p, ceil(totalEdgeCost+ newEdgeCost))
                        enqueue!(frontier, newQ, ceil(f_x))
                    end
                end

            end
        end
    end

    # Return None if no solution found
    #@printf("No solution found! This is length of frontier, %d\n", length(frontier))
    finalPathCost = Void
    isPathFound = false
    pathNodes = Void
    return (finalPathCost, isPathFound, pathNodes)
end

ext: jl


text:
# ref: https://github.com/apache/parquet-format/blob/master/Encodings.md

const MSB = 0x80
const MASK7 = 0x7f
const MASK8 = 0xff
const MASK3 = 0x07
function MASKN(nbits)
    T = byt2uitype_small(bit2bytewidth(nbits))
    O = convert(T, 0x1)
    (O << nbits) - O
end

bitwidth(i) = ceil(Int, log(2, i+1))
bytewidth(i) = bit2bytewidth(bitwidth(i))
bit2bytewidth(i) = ceil(Int, i/8)
byt2itype(i) = (i <= 4) ? Int32 : (i <= 8) ? Int64 : Int128
byt2uitype(i) = (i <= 4) ? UInt32 : (i <= 8) ? UInt64 : UInt128
byt2uitype_small(i) = (i <= 1) ? UInt8 : (i <= 2) ? UInt16 : (i <= 4) ? UInt32 : (i <= 8) ? UInt64 : UInt128

read_fixed(io::IO, typ::Type{UInt32}) = _read_fixed(io, convert(UInt32,0), 4)
read_fixed(io::IO, typ::Type{UInt64}) = _read_fixed(io, convert(UInt64,0), 8)
read_fixed(io::IO, typ::Type{Int32}) = reinterpret(Int32, _read_fixed(io, convert(UInt32,0), 4))
read_fixed(io::IO, typ::Type{Int64}) = reinterpret(Int64, _read_fixed(io, convert(UInt64,0), 8))
read_fixed(io::IO, typ::Type{Int128}) = reinterpret(Int128, _read_fixed(io, convert(UInt128, 0), 12))   # INT96: 12 bytes little endian
read_fixed(io::IO, typ::Type{Float32}) = reinterpret(Float32, _read_fixed(io, convert(UInt32,0), 4))
read_fixed(io::IO, typ::Type{Float64}) = reinterpret(Float64, _read_fixed(io, convert(UInt64,0), 8))
function _read_fixed(io::IO, ret::T, N::Int) where {T <: Unsigned}
    for n in 0:(N-1)
        byte = convert(T, read(io, UInt8))
        ret |= (byte << *(8,n))
    end
    ret
end

function _read_varint(io::IO, ::Type{T}) where {T <: Integer}
    res = zero(T)
    n = 0
    byte = UInt8(MSB)
    while (byte & MSB) != 0
        byte = read(io, UInt8)
        res |= (convert(T, byte & MASK7) << (7*n))
        n += 1
    end
    # in case of overflow, consider it as missing field and return default value
    if (n-1) > sizeof(T)
        #@debug("overflow reading $T. returning 0")
        return zero(T)
    end
    res
end

# parquet types:           BOOLEAN,      INT32,    INT64,    INT96,   FLOAT,   DOUBLE, BYTE_ARRAY, FIXED_LEN_BYTE_ARRAY
# enum values:                   0,          1,        2,        3,       4,        5,          6,                   7
const PLAIN_PROTOBUF_TYPES = ("bool", "sint32", "sint64", "sint64", "float", "double",    "bytes",              "bytes")

# parquet types:           BOOLEAN, INT32, INT64, INT96,    FLOAT,   DOUBLE, BYTE_ARRAY, FIXED_LEN_BYTE_ARRAY
# enum values:                   0,     1,     2,     3,        4,        5,          6,                    7
const PLAIN_THRIFT_TYPES = ("bool", "i32", "i64", "i64", "double", "double",   "binary",            "binary")

# parquet types:   BOOLEAN, INT32, INT64,  INT96,   FLOAT,  DOUBLE, BYTE_ARRAY, FIXED_LEN_BYTE_ARRAY
# enum values:           0,     1,     2,      3,       4,       5,          6,                    7
const PLAIN_JTYPES = (Bool, Int32, Int64, Int128, Float32, Float64,      UInt8,               UInt8)

# read plain encoding (PLAIN = 0)
function read_plain(io::IO, typ::Int32, jtype::Type{T}=PLAIN_JTYPES[typ+1]) where {T}
    if typ == _Type.FIXED_LEN_BYTE_ARRAY
        #@debug("reading fixedlenbytearray length:$count")
        read!(io, Array{UInt8}(count))
    elseif typ == _Type.BYTE_ARRAY
        count = read_fixed(io, Int32)
        #@debug("reading bytearray length:$count")
        read!(io, Array{UInt8}(undef, count))
    elseif typ == _Type.BOOLEAN
        error("not implemented")
    else
        #@debug("reading type:$jtype, typenum:$typ")
        read_fixed(io, jtype)
    end
end

# read plain values or dictionary (PLAIN_DICTIONARY = 2)
function read_plain_values(io::IO, count::Integer, typ::Int32)
    @debug("reading plain values type:$typ, count:$count")
    arr = [read_plain(io, typ) for i in 1:count]
    @debug("read $(length(arr)) plain values")
    arr
end

# read rle dictionary (RLE_DICTIONARY = 8, or PLAIN_DICTIONARY = 2 in a data page)
function read_rle_dict(io::IO, count::Integer)
    bits = read(io, UInt8)
    @debug("reading rle dictionary bits:$bits")
    arr = read_hybrid(io, count, bits; read_len=false)
    @debug("read $(length(arr)) dictionary values")
    arr
end

# read RLE or bit backed format (RLE = 3)
function read_hybrid(io::IO, count::Integer, bits::Integer, byt::Int=bit2bytewidth(bits), typ::Type{T}=byt2itype(byt), arr::Vector{T}=Array{T}(undef, count); read_len::Bool=true) where {T <: Integer}
    len = read_len ? read_fixed(io, Int32) : Int32(0)
    @debug("reading hybrid data length:$len, count:$count, bits:$bits")
    arrpos = 1
    while arrpos <= count
        runhdr = _read_varint(io, Int)
        isbitpack = ((runhdr & 0x1) == 0x1)
        runhdr >>= 1
        nitems = isbitpack ? min(runhdr*8, count - arrpos + 1) : runhdr
        #@debug("nitems=$nitems, isbitpack:$isbitpack, runhdr:$runhdr, remaininglen: $(count - arrpos + 1)")
        #@debug("creating sub array for $nitems items at $arrpos, total length:$(length(arr))")
        #subarr = pointer_to_array(pointer(arr, arrpos), nitems)
        subarr = unsafe_wrap(Array, pointer(arr, arrpos), nitems, own=false)

        if isbitpack
            read_bitpacked_run(io, runhdr, bits, byt, typ, subarr)
        else # rle
            read_rle_run(io, runhdr, bits, byt, typ, subarr)
        end
        arrpos += nitems
    end
    arr
end

function read_rle_run(io::IO, count::Integer, bits::Integer, byt::Int=bit2bytewidth(bits), typ::Type{T}=byt2itype(byt), arr::Vector{T}=Array{T}(count)) where {T <: Integer}
    @debug("read_rle_run. count:$count, typ:$T, nbits:$bits, nbytes:$byt")
    arr[1:count] .= reinterpret(T, _read_fixed(io, zero(byt2uitype(byt)), byt))
    arr
end

function read_bitpacked_run(io::IO, grp_count::Integer, bits::Integer, byt::Int=bit2bytewidth(bits), typ::Type{T}=byt2itype(byt), arr::Vector{T}=Array{T}(undef, grp_count*8)) where {T <: Integer}
    count = min(grp_count * 8, length(arr))
    # multiple of 8 values at a time are bit packed together
    nbytes = bits * grp_count # same as: round(Int, (bits * grp_count * 8) / 8)
    #@debug("read_bitpacked_run. grp_count:$grp_count, count:$count, nbytes:$nbytes, nbits:$bits, available:$(bytesavailable(io))")
    data = Array{UInt8}(undef, min(nbytes, bytesavailable(io)))
    read!(io, data)

    mask = MASKN(bits)
    V = typeof(mask)
    bitbuff = zero(V)
    nbitsbuff = 0
    shift = 0

    arridx = 1
    dataidx = 1
    while arridx <= count
        #@debug("arridx:$arridx nbitsbuff:$nbitsbuff shift:$shift bits:$bits")
        if nbitsbuff > 0
            # we have leftover bits, which must be appended
            arr[arridx] = bitbuff & MASKN(nbitsbuff)
            shift = nbitsbuff
            nbitsbuff = 0
        end

        # fill buffer
        while (nbitsbuff + shift) < bits
             # shift 8 bits and read directly into bitbuff
            bitbuff <<= 8
            bitbuff |= data[dataidx]
            dataidx += 1
            nbitsbuff += 8
        end

        # set values
        while ((nbitsbuff + shift) >= bits) && (arridx <= count)
            if shift > 0
                remshift = bits - shift
                #@debug("setting part from bitbuff nbitsbuff:$nbitsbuff, shift:$shift, remshift:$remshift")
                arr[arridx] |= convert(T, (bitbuff << shift) & mask)
                bitbuff >>= remshift
                nbitsbuff -= remshift
                shift = 0
            else
                #@debug("setting all from bitbuff nbitsbuff:$nbitsbuff")
                arr[arridx] = convert(T, bitbuff & mask)
                bitbuff >>= bits
                nbitsbuff -= bits
            end
            arridx += 1
        end
    end
    arr
end

# read bit packed in deprecated format (BIT_PACKED = 4)
function read_bitpacked_run_old(io::IO, count::Integer, bits::Integer, byt::Int=bit2bytewidth(bits), typ::Type{T}=byt2itype(byt), arr::Vector{T}=Array{T}(undef, count)) where {T <: Integer}
    # multiple of 8 values at a time are bit packed together
    nbytes = round(Int, (bits * count) / 8)
    @debug("read_bitpacked_run. count:$count, nbytes:$nbytes, nbits:$bits")
    data = Array{UInt8}(undef, nbytes)
    read!(io, data)

    # the mask is of the smallest bounding type for bits
    # T is one of the types that map on to the appropriate Julia type in Parquet (which may be larger than the mask type)
    mask = MASKN(bits)
    V = typeof(mask)
    bitbuff = zero(V)
    nbitsbuff = 0

    arridx = 1
    dataidx = 1
    while arridx <= count
        diffnbits = bits - nbitsbuff
        while diffnbits > 8
            # shift 8 bits and read directly into bitbuff
            bitbuff <<= 8
            bitbuff |= data[dataidx]
            dataidx += 1
            nbitsbuff += 8
            diffnbits -= 8
        end

        if diffnbits > 0
            # read next byte from input
            nxtdata = data[dataidx]
            dataidx += 1
            # shift bitbuff by diffnbits, add diffnbits and set result
            nbitsbuff = 8 - diffnbits
            arr[arridx] = convert(T, ((bitbuff << diffnbits) | (nxtdata >> nbitsbuff)) & mask)
            arridx += 1
            # keep remaining bits in bitbuff
            bitbuff <<= 8
            bitbuff |= nxtdata
        else
            # set result
            arr[arridx] = convert(T, (bitbuff >> abs(diffnbits)) & mask)
            arridx += 1
            nbitsbuff -= bits
        end
    end
    arr
end


text:
## rod_types.jl
# James Gabbard, November 30th, 2020
#
# Interface for specifying a physical system composed of elastic rods

# ------------------------------------------------------------------------------
#  Types
# ------------------------------------------------------------------------------

struct basic_rod{T<:Real}
    x::AbstractArray{T} # (ns + 2) x 3
    d::AbstractArray{T} # (ns + 1) x 3
end

struct rod_delta{T<:Real}
    Δx::AbstractArray{T} # (ns + 2) x 3
    Δθ::AbstractArray{T} # (ns + 1) x 1
end

# Strains
struct rod_strains{T<:Real}
    l::Matrix{T} # ns + 1
    κ::Matrix{T} # ns x 2
    τ::Matrix{T} # ns
end

# ------------------------------------------------------------------------------
#  Allocation
# ------------------------------------------------------------------------------

function copy(s::rod_strains)
    rod_strains(Base.copy(s.l), Base.copy(s.κ), Base.copy(s.τ))
end

function copy(r::basic_rod)
    basic_rod(Base.copy(r.x), Base.copy(r.d))
end

function copy!(r1::basic_rod, r2::basic_rod)
    r1.x .= r2.x
    r1.d .= r2.d
end

function allocate_rod(T::Type, ns::Int)
    x = Matrix{T}(undef, ns+2, 3)
    d = Matrix{T}(undef, ns+1, 3)
    basic_rod(x,d)
end

function allocate_strain(T::Type, ns::Int)
    l = Matrix{T}(undef, ns+1, 1)
    κ = Matrix{T}(undef, ns, 2)
    τ = Matrix{T}(undef, ns, 1)
    rod_strains(l, κ, τ)
end

function allocate_delta(T::Type, ns::Int)
    Δx = Matrix{T}(undef, ns+2, 3)
    Δθ = Matrix{T}(undef, ns+1, 1)
    return rod_delta(Δx, Δθ)
end

function zero_delta(T::Type, ns::Int)
    return rod_delta(zeros(T, ns+2, 3), zeros(T, ns+1, 1))
end

# ----------------------------------------------------------------------------------
#  Elastic Energy Computation
# ----------------------------------------------------------------------------------
# Rod properties: the relevant elastic properties of the rod. Can be scalar
#   k - stretching stiffness
#   B - bending stiffness principal components
#   β - twisting stiffness
# For convenience, the director field MUST match the eigenvectors of the
# bending stiffness tensor. Thus B = (B[1] d1 ⊗ d1) + (B[2] d2 ⊗ d2).

abstract type rod_properties end

# All properties vary along the length
struct vector_rod_properties{T<:Real} <: rod_properties
    k::Vector{T} # ns + 1
    B::Matrix{T} # ns x 2
    β::Vector{T} # ns
end

# Constant properties, anisotropic cross section
struct scalar_rod_properties{T<:Real} <: rod_properties
    k::T
    B::Matrix{T}# 1 x 2
    β::T
end


text:
module ShaftFreeMotion

using ModiaLang

import Modia3D
using  Modia3D.ModiaInterface

Shaft = Model(
    Length = 1.0,
    Diameter = 0.2,
    visualMaterial = VisualMaterial(color="IndianRed1", transparency=0.5),
    world = Object3D(feature=Scene(gravityField=UniformGravityField(g=0.3, n=[0, 0, -1]))),
    worldFrame = Object3D(parent=:world,
                          feature=Visual(shape=CoordinateSystem(length=:Diameter))),
    shaft = Object3D(feature=Solid(shape=Cylinder(axis=3, diameter=:Diameter, length=:Length),
                                   massProperties=MassProperties(; mass=84.7154, Ixx=7.2711, Iyy=7.2711, Izz=0.4230),
                                   visualMaterial=:(visualMaterial))),
    free = FreeMotion(obj1=:world, obj2=:shaft)
)

model = Model(
    shaft = buildModia3D(Shaft | Map(Length=1.0, Diameter=0.2, free = Map(v   = Var(init = [0.0, 0.1, 0.6]),
                                                                          rot = Var(init = [deg2rad(30), deg2rad(20), deg2rad(10)]),
                                                                          w   = Var(init = [1.0, 2.0, 3.0]))))
)

#@showModel model

shaft = @instantiateModel(model, aliasReduction=false, unitless=true, log=false, logStateSelection=false, logCode=false)

#@showModel shaft.p[1]

stopTime = 5.0
requiredFinalStates=[-1.7224720653038268e-14, 0.4999999999999575, -0.750000016852883, -1.5681975307975595e-14, 0.0999999999999862, -0.8999999999999555, 12.518049838490617, -0.9018643787079454, 13.979844144766544, 2.0096818051930816, -0.9803470582617598, 2.9999999999999933]
simulate!(shaft, stopTime=stopTime, log=true, logStates=true, requiredFinalStates=requiredFinalStates)

@usingModiaPlot
plot(shaft, ["shaft.free.r", "shaft.free.rot", "shaft.free.v", "shaft.free.w"], figure=1)

end


text:
"""
    coef(x::EquateMethod)

Return equating coefficient. The input object is equated result under the SG and NEAT design method.
"""
function coef(x::EquateMethod)
    if isnothing(x.estimates)
        x.table[:, 2]
    else
        x.estimates
    end
end


text:
#####
##### constructors
#####

ChainRules.@non_differentiable (::Type{T} where {T<:Array})(::UndefInitializer, args...)

function frule((_, ẋ), ::Type{T}, x::AbstractArray) where {T<:Array}
    return T(x), T(ẋ)
end

function frule((_, ẋ), ::Type{AbstractArray{T}}, x::AbstractArray) where {T}
    return AbstractArray{T}(x), AbstractArray{T}(ẋ)
end

function rrule(::Type{T}, x::AbstractArray) where {T<:Array}
    project_x = ProjectTo(x)
    Array_pullback(ȳ) = (NoTangent(), project_x(ȳ))
    return T(x), Array_pullback
end

# This abstract one is used for `float(x)` and other float conversion purposes:
function rrule(::Type{AbstractArray{T}}, x::AbstractArray) where {T}
    project_x = ProjectTo(x)
    AbstractArray_pullback(ȳ) = (NoTangent(), project_x(ȳ))
    return AbstractArray{T}(x), AbstractArray_pullback
end

#####
##### `vect`
#####

@non_differentiable Base.vect()

function frule((_, ẋs...), ::typeof(Base.vect), xs::Number...)
    return Base.vect(xs...), Base.vect(_instantiate_zeros(ẋs, xs)...)
end

# Case of uniform type `T`: the data passes straight through,
# so no projection should be required.
function rrule(::typeof(Base.vect), X::Vararg{T, N}) where {T, N}
    vect_pullback(ȳ) = (NoTangent(), NTuple{N}(ȳ)...)
    return Base.vect(X...), vect_pullback
end

# Numbers and arrays are often promoted, to make a uniform vector.
# ProjectTo here reverses this
function rrule(
    ::typeof(Base.vect),
    X::Vararg{Union{Number,AbstractArray{<:Number}}, N},
) where {N}
    projects = map(ProjectTo, X)
    function vect_pullback(ȳ)
        X̄ = ntuple(n -> projects[n](ȳ[n]), N)
        return (NoTangent(), X̄...)
    end
    return Base.vect(X...), vect_pullback
end

# Data is unmodified, so no need to project.
function rrule(::typeof(Base.vect), X::Vararg{Any,N}) where {N}
    vect_pullback(ȳ) = (NoTangent(), ntuple(n -> ȳ[n], N)...)
    return Base.vect(X...), vect_pullback
end

"""
    _instantiate_zeros(ẋs, xs)

Forward rules for `vect`, `cat` etc may receive a mixture of data and `ZeroTangent`s.
To avoid `vect(1, ZeroTangent(), 3)` or worse `vcat([1,2], ZeroTangent(), [6,7])`, this
materialises each zero `ẋ` to be `zero(x)`.
"""
_instantiate_zeros(ẋs, xs) = map(_i_zero, ẋs, xs)
_i_zero(ẋ, x) = ẋ
_i_zero(ẋ::AbstractZero, x) = zero(x)
# Possibly this won't work for partly non-diff arrays, sometihng like `gradient(x -> ["abc", x][end], 1)`
# may give a MethodError for `zero` but won't be wrong.

# Fast paths. Should it also collapse all-Zero cases?
_instantiate_zeros(ẋs::Tuple{Vararg{<:Number}}, xs) = ẋs
_instantiate_zeros(ẋs::Tuple{Vararg{<:AbstractArray}}, xs) = ẋs
_instantiate_zeros(ẋs::AbstractArray{<:Number}, xs) = ẋs
_instantiate_zeros(ẋs::AbstractArray{<:AbstractArray}, xs) = ẋs

#####
##### `copyto!`
#####

function frule((_, ẏ, ẋ), ::typeof(copyto!), y::AbstractArray, x)
    return copyto!(y, x), copyto!(ẏ, ẋ)
end

function frule((_, ẏ, _, ẋ), ::typeof(copyto!), y::AbstractArray, i::Integer, x, js::Integer...)
    return copyto!(y, i, x, js...), copyto!(ẏ, i, ẋ, js...)
end

#####
##### `reshape`
#####

function frule((_, ẋ), ::typeof(reshape), x::AbstractArray, dims...)
    return reshape(x, dims...), reshape(ẋ, dims...)
end

function rrule(::typeof(reshape), A::AbstractArray, dims...)
    ax = axes(A)
    project = ProjectTo(A)  # Projection is here for e.g. reshape(::Diagonal, :)
    ∂dims = broadcast(Returns(NoTangent()), dims)
    reshape_pullback(Ȳ) = (NoTangent(), project(reshape(Ȳ, ax)), ∂dims...)
    return reshape(A, dims...), reshape_pullback
end

#####
##### `dropdims`
#####

function frule((_, ẋ), ::typeof(dropdims), x::AbstractArray; dims)
    return dropdims(x; dims), dropdims(ẋ; dims)
end

function rrule(::typeof(dropdims), A::AbstractArray; dims)
    ax = axes(A)
    project = ProjectTo(A)
    dropdims_pullback(Ȳ) = (NoTangent(), project(reshape(Ȳ, ax)))
    return dropdims(A; dims), dropdims_pullback
end

#####
##### `permutedims`
#####

function frule((_, ẋ), ::typeof(permutedims), x::AbstractArray, perm...)
    return permutedims(x, perm...), permutedims(ẋ, perm...)
end

function frule((_, ẏ, ẋ), ::typeof(permutedims!), y::AbstractArray, x::AbstractArray, perm...)
    return permutedims!(y, x, perm...), permutedims!(ẏ, ẋ, perm...)
end

function frule((_, ẋ), ::Type{<:PermutedDimsArray}, x::AbstractArray, perm)
    return PermutedDimsArray(x, perm), PermutedDimsArray(ẋ, perm)
end

function rrule(::typeof(permutedims), x::AbstractVector)
    project = ProjectTo(x)
    permutedims_pullback_1(dy) = (NoTangent(), project(permutedims(unthunk(dy))))
    return permutedims(x), permutedims_pullback_1
end

function rrule(::typeof(permutedims), x::AbstractArray, perm)
    pr = ProjectTo(x)  # projection restores e.g. transpose([1,2,3])
    permutedims_back_2(dy) = (NoTangent(), pr(permutedims(unthunk(dy), invperm(perm))), NoTangent())
    return permutedims(x, perm), permutedims_back_2
end

function rrule(::Type{<:PermutedDimsArray}, x::AbstractArray, perm)
    pr = ProjectTo(x)
    permutedims_back_3(dy) = (NoTangent(), pr(permutedims(unthunk(dy), invperm(perm))), NoTangent())
    return PermutedDimsArray(x, perm), permutedims_back_3
end

#####
##### `repeat`
#####

function frule((_, ẋs), ::typeof(repeat), xs::AbstractArray, cnt...; kw...)
    return repeat(xs, cnt...; kw...), repeat(ẋs, cnt...; kw...)
end

function rrule(::typeof(repeat), xs::AbstractArray; inner=ntuple(Returns(1), ndims(xs)), outer=ntuple(Returns(1), ndims(xs)))

    project_Xs = ProjectTo(xs)
    S = size(xs)
    function repeat_pullback(ȳ)
        dY = unthunk(ȳ)
        Δ′ = zero(xs)
        # Loop through each element of Δ, calculate source dimensions, accumulate into Δ′
        for (dest_idx, val) in pairs(IndexCartesian(), dY)
            # First, round dest_idx[dim] to nearest gridpoint defined by inner[dim], then
            # wrap around based on original size S.
            src_idx = [mod1(div(dest_idx[dim] - 1, inner[dim]) + 1, S[dim]) for dim in 1:length(S)]
            Δ′[src_idx...] += val
        end
        x̄ = project_Xs(Δ′)
        return (NoTangent(), x̄)
    end

    return repeat(xs; inner = inner, outer = outer), repeat_pullback
end

function rrule(::typeof(repeat), xs::AbstractArray, counts::Integer...)

    project_Xs = ProjectTo(xs)
    S = size(xs)
    function repeat_pullback(ȳ)
        dY = unthunk(ȳ)
        size2ndims = ntuple(d -> isodd(d) ? get(S, 1+d÷2, 1) : get(counts, d÷2, 1), 2*ndims(dY))
        reduced = sum(reshape(dY, size2ndims); dims = ntuple(d -> 2d, ndims(dY)))
        x̄ = project_Xs(reshape(reduced, S))
        return (NoTangent(), x̄, map(Returns(NoTangent()), counts)...)
    end
    return repeat(xs, counts...), repeat_pullback
end

#####
##### `hcat`
#####

function frule((_, ẋs...), ::typeof(hcat), xs...)
    return hcat(xs...), hcat(_instantiate_zeros(ẋs, xs)...)
end

function rrule(::typeof(hcat), Xs::Union{AbstractArray, Number}...)
    Y = hcat(Xs...)  # note that Y always has 1-based indexing, even if X isa OffsetArray
    ndimsY = Val(ndims(Y))  # this avoids closing over Y, Val() is essential for type-stability
    sizes = map(size, Xs)   # this avoids closing over Xs
    project_Xs = map(ProjectTo, Xs)
    function hcat_pullback(ȳ)
        dY = unthunk(ȳ)
        hi = Ref(0)  # Ref avoids hi::Core.Box
        dXs = map(project_Xs, sizes) do project, sizeX
            ndimsX = length(sizeX)
            lo = hi[] + 1
            hi[] += get(sizeX, 2, 1)
            ind = ntuple(ndimsY) do d
                if d==2
                    d > ndimsX ? lo : lo:hi[]
                else
                    d > ndimsX ? 1 : (:)
                end
            end
            dX = if ndimsX > 0
                # Here InplaceableThunk breaks @inferred, removed for now
                # InplaceableThunk(dX -> dX .+= view(dY, ind...), @thunk(dY[ind...]))
                dY[ind...]
            else
                # This is a hack to perhaps avoid GPU scalar indexing
                sum(view(dY, ind...))
            end
            return project(dX)
        end
        return (NoTangent(), dXs...)
    end
    return Y, hcat_pullback
end

function frule((_, _, Ȧs), ::typeof(reduce), ::typeof(hcat), As::AbstractVector{<:AbstractVecOrMat})
    return reduce(hcat, As), reduce(hcat, _instantiate_zeros(Ȧs, As))
end

function rrule(::typeof(reduce), ::typeof(hcat), As::AbstractVector{<:AbstractVecOrMat})
    widths = map(A -> size(A,2), As)
    function reduce_hcat_pullback_2(dY)
        hi = Ref(0)
        dAs = map(widths) do w
            lo = hi[]+1
            hi[] += w
            dY[:, lo:hi[]]
        end
        return (NoTangent(), NoTangent(), dAs)
    end
    return reduce(hcat, As), reduce_hcat_pullback_2
end

function rrule(::typeof(reduce), ::typeof(hcat), As::AbstractVector{<:AbstractVector})
    axe = axes(As,1)
    function reduce_hcat_pullback_1(dY)
        hi = Ref(0)
        dAs = map(_ -> dY[:, hi[]+=1], axe)
        return (NoTangent(), NoTangent(), dAs)
    end
    return reduce(hcat, As), reduce_hcat_pullback_1
end

#####
##### `vcat`
#####

function frule((_, ẋs...), ::typeof(vcat), xs...)
    return vcat(xs...), vcat(_instantiate_zeros(ẋs, xs)...)
end

function rrule(::typeof(vcat), Xs::Union{AbstractArray, Number}...)
    Y = vcat(Xs...)
    ndimsY = Val(ndims(Y))
    sizes = map(size, Xs)
    project_Xs = map(ProjectTo, Xs)
    function vcat_pullback(ȳ)
        dY = unthunk(ȳ)
        hi = Ref(0)
        dXs = map(project_Xs, sizes) do project, sizeX
            ndimsX = length(sizeX)
            lo = hi[] + 1
            hi[] += get(sizeX, 1, 1)
            ind = ntuple(ndimsY) do d
                if d==1
                    d > ndimsX ? lo : lo:hi[]
                else
                    d > ndimsX ? 1 : (:)
                end
            end
            dX = if ndimsX > 0
                # InplaceableThunk(@thunk(dY[ind...]), dX -> dX .+= view(dY, ind...))
                dY[ind...]
            else
                sum(view(dY, ind...))
            end
            return project(dX)
        end
        return (NoTangent(), dXs...)
    end
    return Y, vcat_pullback
end

function frule((_, _, Ȧs), ::typeof(reduce), ::typeof(vcat), As::AbstractVector{<:AbstractVecOrMat})
    return reduce(vcat, As), reduce(vcat, _instantiate_zeros(Ȧs, As))
end

function rrule(::typeof(reduce), ::typeof(vcat), As::AbstractVector{<:AbstractVecOrMat})
    Y = reduce(vcat, As)
    ndimsY = Val(ndims(Y))
    heights = map(A -> size(A,1), As)
    function reduce_vcat_pullback(dY)
        hi = Ref(0)
        dAs = map(heights) do z
            lo = hi[]+1
            hi[] += z
            ind = ntuple(d -> d==1 ? (lo:hi[]) : (:), ndimsY)
            dY[ind...]
        end
        return (NoTangent(), NoTangent(), dAs)
    end
    return Y, reduce_vcat_pullback
end

#####
##### `cat`
#####

_val(::Val{x}) where {x} = x

function frule((_, ẋs...), ::typeof(cat), xs...; dims)
    return cat(xs...; dims), cat(_instantiate_zeros(ẋs, xs)...; dims)
end

function rrule(::typeof(cat), Xs::Union{AbstractArray, Number}...; dims)
    Y = cat(Xs...; dims=dims)
    cdims = dims isa Val ? Int(_val(dims)) : dims isa Integer ? Int(dims) : Tuple(dims)
    ndimsY = Val(ndims(Y))
    sizes = map(size, Xs)
    project_Xs = map(ProjectTo, Xs)
    function cat_pullback(ȳ)
        dY = unthunk(ȳ)
        prev = fill(0, _val(ndimsY))  # note that Y always has 1-based indexing, even if X isa OffsetArray
        dXs = map(project_Xs, sizes) do project, sizeX
            ndimsX = length(sizeX)
            index = ntuple(ndimsY) do d
                if d in cdims
                    d > ndimsX ? (prev[d]+1) : (prev[d]+1:prev[d]+sizeX[d])
                else
                    d > ndimsX ? 1 : (:)
                end
            end
            for d in cdims
                prev[d] += get(sizeX, d, 1)
            end
            dX = if ndimsX > 0
                # InplaceableThunk(@thunk(dY[index...]), dX -> dX .+= view(dY, index...))
                dY[index...]
            else
                sum(view(dY, index...))
            end
            return project(dX)
        end
        return (NoTangent(), dXs...)
    end
    return Y, cat_pullback
end

#####
##### `hvcat`
#####

function frule((_, _, ẋs...), ::typeof(hvcat), rows, xs...)
    return hvcat(rows, xs...), hvcat(rows, _instantiate_zeros(ẋs, xs)...)
end

function rrule(::typeof(hvcat), rows, values::Union{AbstractArray, Number}...)
    Y = hvcat(rows, values...)
    cols = size(Y,2)
    ndimsY = Val(ndims(Y))
    sizes = map(size, values)
    project_Vs = map(ProjectTo, values)
    function hvcat_pullback(dY)
        prev = fill(0, 2)
        dXs = map(project_Vs, sizes) do project, sizeX
            ndimsX = length(sizeX)
            index = ntuple(ndimsY) do d
                if d in (1, 2)
                    d > ndimsX ? (prev[d]+1) : (prev[d]+1:prev[d]+sizeX[d])
                else
                    d > ndimsX ? 1 : (:)
                end
            end
            prev[2] += get(sizeX, 2, 1)
            if prev[2] == cols
                prev[2] = 0
                prev[1] += get(sizeX, 1, 1)
            end
            project(dY[index...])
        end
        return (NoTangent(), NoTangent(), dXs...)
    end
    return Y, hvcat_pullback
end

#####
##### `reverse`
#####

# 1-dim case allows start/stop, N-dim case takes dims keyword
# whose defaults changed in Julia 1.6... just pass them all through:

function frule((_, ẋ), ::typeof(reverse), x::Union{AbstractArray, Tuple}, args...; kw...)
    return reverse(x, args...; kw...), reverse(ẋ, args...; kw...)
end

function frule((_, ẋ), ::typeof(reverse!), x::Union{AbstractArray, Tuple}, args...; kw...)
    return reverse!(x, args...; kw...), reverse!(ẋ, args...; kw...)
end

function rrule(::typeof(reverse), x::Union{AbstractArray, Tuple}, args...; kw...)
    nots = map(Returns(NoTangent()), args)
    function reverse_pullback(dy)
        dx = @thunk reverse(unthunk(dy), args...; kw...)
        return (NoTangent(), dx, nots...)
    end
    return reverse(x, args...; kw...), reverse_pullback
end

#####
##### `circshift`
#####

function frule((_, ẋ), ::typeof(circshift), x::AbstractArray, shifts)
    return circshift(x, shifts), circshift(ẋ, shifts)
end

function frule((_, ẏ, ẋ), ::typeof(circshift!), y::AbstractArray, x::AbstractArray, shifts)
    return circshift!(y, x, shifts), circshift!(ẏ, ẋ, shifts)
end

function rrule(::typeof(circshift), x::AbstractArray, shifts)
    function circshift_pullback(dy)
        dx = @thunk circshift(unthunk(dy), map(-, shifts))
        # Note that circshift! is useless for InplaceableThunk, as it overwrites completely
        return (NoTangent(), dx, NoTangent())
    end
    return circshift(x, shifts), circshift_pullback
end

#####
##### `fill`
#####

function frule((_, ẋ), ::typeof(fill), x::Any, dims...)
    return fill(x, dims...), fill(ẋ, dims...)
end

function frule((_, ẏ, ẋ), ::typeof(fill!), y::AbstractArray, x::Any)
    return fill!(y, x), fill!(ẏ, ẋ)
end

function rrule(::typeof(fill), x::Any, dims...)
    project = ProjectTo(x)
    nots = map(Returns(NoTangent()), dims)
    fill_pullback(Ȳ) = (NoTangent(), project(sum(Ȳ)), nots...)
    return fill(x, dims...), fill_pullback
end

#####
##### `filter`
#####

function frule((_, _, ẋ), ::typeof(filter), f, x::AbstractArray)
    inds = findall(f, x)
    return x[inds], ẋ[inds]
end

function rrule(::typeof(filter), f, x::AbstractArray)
    inds = findall(f, x)
    y, back = rrule(getindex, x, inds)
    function filter_pullback(dy)
        _, dx, _ = back(dy)
        return (NoTangent(), NoTangent(), dx)
    end
    return y, filter_pullback
end

#####
##### `findmax`, `maximum`, etc.
#####

for findm in (:findmin, :findmax)
    findm_pullback = Symbol(findm, :_pullback)

    @eval function frule((_, ẋ), ::typeof($findm), x; dims=:)
        y, ind = $findm(x; dims=dims)
        return (y, ind), Tangent{typeof((y, ind))}(ẋ[ind], NoTangent())
    end

    @eval function rrule(::typeof($findm), x::AbstractArray; dims=:)
        y, ind = $findm(x; dims=dims)
        project = ProjectTo(x)
        # This pullback is a lot like the one for getindex. Ideally they would probably be combined?
        function $findm_pullback((dy, _))  # this accepts e.g. Tangent{Tuple{Float64, Int64}}(4.0, nothing)
            dy isa AbstractZero && return (NoTangent(), NoTangent())
            x_thunk = @thunk project(_zerolike_writeat(x, unthunk(dy), dims, ind))
            x_ithunk = InplaceableThunk(x_thunk) do dx
                if dims isa Colon
                    view(dx, ind) .= view(dx, ind) .+ Ref(unthunk(dy))
                else
                    view(dx, ind) .= view(dx, ind) .+ unthunk(dy)  # this could be .+=, but not on Julia 1.0
                end
                dx
            end
            return (NoTangent(), x_ithunk)
        end
        return (y, ind), $findm_pullback
    end
end

# This function is roughly `setindex!(zero(x), dy, inds...)`:

function _zerolike_writeat(x::AbstractArray{<:Number}, dy, dims, inds...)
    # It's unfortunate to close over `x`, but `similar(typeof(x), axes(x))` doesn't
    # allow `eltype(dy)`, nor does it work for many structured matrices.
    dx = fill!(similar(x, eltype(dy), axes(x)), 0)
    view(dx, inds...) .= dy  # possibly 0-dim view, allows dy::Number and dy::Array, and dx::CuArray
    dx
end
function _zerolike_writeat(x::AbstractArray, dy, dims, inds...)
    # Since we have `x`, we can also handle arrays of arrays.
    dx = map(zero, x)
    if dims isa Colon
        view(dx, inds...) .= Ref(dy)
    else
        view(dx, inds...) .= dy
    end
    dx
end

# Allow for second derivatives, by writing rules for `_zerolike_writeat`;
# these rules are the reason it takes a `dims` argument.

function frule((_, _, dẏ), ::typeof(_zerolike_writeat), x, dy, dims, inds...)
    return _zerolike_writeat(x, dy, dims, inds...), _zerolike_writeat(x, dẏ, dims, inds...)
end

function rrule(::typeof(_zerolike_writeat), x, dy, dims, inds...)
    z = _zerolike_writeat(x, dy, dims, inds...)
    function _zerolike_writeat_pullback(dz)
        dx = sum(view(unthunk(dz), inds...); dims=dims)
        nots = map(_ -> NoTangent(), inds)
        return (NoTangent(), NoTangent(), dx, NoTangent(), nots...)
    end
    return z, _zerolike_writeat_pullback
end

# These rules for `maximum` pick the same subgradient as `findmax`:

function frule((_, ẋ), ::typeof(maximum), x; dims=:)
    y, ind = findmax(x; dims=dims)
    return y, ẋ[ind]
end

function rrule(::typeof(maximum), x::AbstractArray; dims=:)
    (y, _), back = rrule(findmax, x; dims=dims)
    maximum_pullback(dy) = back((dy, nothing))
    return y, maximum_pullback
end

function frule((_, ẋ), ::typeof(minimum), x; dims=:)
    y, ind = findmin(x; dims=dims)
    return y, ẋ[ind]
end

function rrule(::typeof(minimum), x::AbstractArray; dims=:)
    (y, _), back = rrule(findmin, x; dims=dims)
    minimum_pullback(dy) = back((dy, nothing))
    return y, minimum_pullback
end

#####
##### `extrema`
#####

function rrule(::typeof(extrema), x::AbstractArray{<:Number}; dims=:)
    if dims isa Colon
        return _extrema_colon(x)
    else
        return _extrema_dims(x, dims)
    end
end

function _extrema_colon(x)
    ylo, ilo = findmin(x)
    yhi, ihi = findmax(x)
    project = ProjectTo(x)
    function extrema_pullback((dylo, dyhi))  # accepts Tangent
        if (dylo, dyhi) isa Tuple{AbstractZero, AbstractZero}
            return (NoTangent(), NoTangent())
        end
        # One argument may be AbstractZero here. Use promote_op because
        # promote_type allows for * as well as +, hence gives Any.
        T = Base.promote_op(+, typeof(dylo), typeof(dyhi))
        x_nothunk = let
        # x_thunk = @thunk begin  # this doesn't infer
            dx = fill!(similar(x, T, axes(x)), false)
            view(dx, ilo) .= dylo
            view(dx, ihi) .= view(dx, ihi) .+ dyhi
            project(dx)
        end
        # x_ithunk = InplaceableThunk(x_thunk) do dx
        #     view(dx, ilo) .= view(dx, ilo) .+ dylo
        #     view(dx, ihi) .= view(dx, ihi) .+ dyhi
        #     dx
        # end
        return (NoTangent(), x_nothunk)
    end
    return (ylo, yhi), extrema_pullback
end

function _extrema_dims(x, dims)
    ylo, ilo = findmin(x; dims=dims)
    yhi, ihi = findmax(x; dims=dims)
    y = similar(ylo, Tuple{eltype(ylo), eltype(yhi)})
    map!(tuple, y, ylo, yhi)  # this is a GPU-friendly version of collect(zip(ylo, yhi))
    project = ProjectTo(x)
    function extrema_pullback_dims(dy_raw)
        dy = unthunk(dy_raw)
        @assert dy isa AbstractArray{<:Tuple{Any,Any}}
        # Can we actually get Array{Tuple{Float64,ZeroTangent}} here? Not sure.
        T = Base.promote_op(+, eltype(dy).parameters...)
        x_nothunk = let
        # x_thunk = @thunk begin  # this doesn't infer
            dx = fill!(similar(x, T, axes(x)), false)
            view(dx, ilo) .= first.(dy)
            view(dx, ihi) .= view(dx, ihi) .+ last.(dy)
            project(dx)
        end
        # x_ithunk = InplaceableThunk(x_thunk) do dx
        #     view(dx, ilo) .= first.(dy)
        #     view(dx, ihi) .= view(dx, ihi) .+ last.(dy)
        #     dx
        # end
        return (NoTangent(), x_nothunk)
    end
    return y, extrema_pullback_dims
end


text:
using DataDeps

register(DataDep(
  "soybean-small",
  "http://archive.ics.uci.edu/ml/datasets/Soybean+%28Large%29",
  "http://archive.ics.uci.edu/ml/machine-learning-databases/soybean/soybean-small.data",
  "f096d1675db0270071311c9f46813b204372370bd68252a5a417bdcff5879717",
  post_fetch_method=(path -> begin
    UCIData.process_dataset(path,
        target_index=36,
        feature_indices=1:35,
        categoric_indices=1:35,
    )
  end),
))

max_stars_repo_name: JackDunnNZ/uci-data

max_issues_repo_name: JackDunnNZ/uci-data

max_forks_repo_name: JackDunnNZ/uci-data


text:
using Base.Test
using IJulia

mktemp() do path, io
    redirect_stdout(IJulia.IJuliaStdio(io, "stdout")) do
        println("print")
    end
    flush(io)
    seek(io, 0)
    @test readstring(io) == "print\n"
    @test_throws ArgumentError redirect_stdout(IJulia.IJuliaStdio(io, "stderr"))
    @test_throws ArgumentError redirect_stdout(IJulia.IJuliaStdio(io, "stdin"))
    @test_throws ArgumentError redirect_stderr(IJulia.IJuliaStdio(io, "stdout"))
    @test_throws ArgumentError redirect_stderr(IJulia.IJuliaStdio(io, "stdin"))
    @test_throws ArgumentError redirect_stdin(IJulia.IJuliaStdio(io, "stdout"))
    @test_throws ArgumentError redirect_stdin(IJulia.IJuliaStdio(io, "stderr"))
end

mktemp() do path, io
    redirect_stderr(IJulia.IJuliaStdio(io, "stderr")) do
        warn("warn")
    end
    flush(io)
    seek(io, 0)
    captured = readstring(io)
    @test (captured == "\e[1m\e[33mWARNING: \e[39m\e[22m\e[33mwarn\e[39m\n" ||
           captured == "WARNING: warn\n")  # output will differ based on whether color is currently enabled
end

mktemp() do path, io
    redirect_stdin(IJulia.IJuliaStdio(io, "stdin")) do
        # We can't actually do anything here because `IJuliaexecute_msg` has not
        # yet been initialized, so we just make sure that redirect_stdin does
        # not error.
    end
end


text:
include("..\\Vehicle\\Spacecraft.jl")
include("..\\solver\\GlobalDictionaries.jl")
include("..\\Environment\\LoadEnvironment.jl")
include("SimulationOptions.jl")
include("Propagator.jl")
import DifferentialEquations: solve, ODEProblem

#A function that executes the a single vehicle simulation. Defines the interface to the users
function sim(vehicle::Type{<:AbstractSpacecraft}, env::Environment, opt::SimulationOptions)

    #Get solver and simulation time  from Simulation options
    solver = ODEALG[opt.ODE_SolverType]
    SimulationTime = opt.SimulationTime
    ####################################################
    #Get EOM (ODEProblem) from the environment structure
    eom = EOM(vehicle, env)
    prob = ODEProblem(eom, vehicle.InitialState, (0, SimulationTime))

    ####################################################
    #Get callbacks from the vehicle systems  (vehiclesystems)

    ####################################################
    #Solve the resulting differential equations
    error("not yet implemented")
    return solve(prob, solver, callback = vehiclesystems, reltol=1e-8, abstol=1e-8)
    ####################################################
end


text:
using Revise
using CMPSKit
using KrylovKit
using OptimKit
using LinearAlgebra
using JLD2

D = 4
optalg = ConjugateGradient(; verbosity = 2, maxiter = 10^6, gradtol = 1e-7);
linalg = GMRES(; krylovdim = D^2, tol = 1e-9);
eigalg = Arnoldi(; krylovdim = D^2, tol = 1e-9);

# Single-boson Lieb-Liniger
Q = Constant(randn(D,D))
R = Constant(randn(D,D))
Ψ = InfiniteCMPS(Q, R)

H = ∫(∂ψ'*∂ψ - 1 * ψ'*ψ + 1 * (ψ')^2*ψ^2, (-Inf,+Inf))
ΨL, ρR, E, e = groundstate(H, Ψ; optalg = optalg, linalg = linalg, eigalg = eigalg)
Q = ΨL.Q
R = ΨL.Rs[1]

# Two independent boson Lieb-Liniger
I = one(Q(0))
Q1 = Constant(kron(Q(0), I))
R1 = Constant(kron(R(0), I))
Q2 = Constant(kron(I, Q(0)))
R2 = Constant(kron(I, R(0)))

Ψ2 = InfiniteCMPS(Q1+Q2, (R1, R2))

H2 = ∫(∂ψ[1]'*∂ψ[1] - 1 * ψ[1]'*ψ[1] + 1 * (ψ[1]')^2*ψ[1]^2 +
        ∂ψ[2]'*∂ψ[2] - 1 * ψ[2]'*ψ[2] + 1 * (ψ[2]')^2*ψ[2]^2 +
        100 * (ψ[1]*ψ[2] - ψ[2]*ψ[1])' * (ψ[1]*ψ[2] - ψ[2]*ψ[1]), (-Inf,+Inf))

expval(∂ψ[1]'*∂ψ[1] - 1 * ψ[1]'*ψ[1] + 1 * (ψ[1]')^2*ψ[1]^2, Ψ2) ≈ e
expval(∂ψ[1]'*∂ψ[1] - 1 * ψ[1]'*ψ[1] + 1 * (ψ[1]')^2*ψ[1]^2, Ψ2) ≈
    expval(∂ψ[2]'*∂ψ[2] - 1 * ψ[2]'*ψ[2] + 1 * (ψ[2]')^2*ψ[2]^2, Ψ2)
expval(density(H2), Ψ2) ≈ 2*e

D = 16
Q = Constant(randn(D,D))
R1 = Constant(randn(D,D))
R2 = Constant(randn(D,D))
Ψ2 = InfiniteCMPS(Q, (R1, R2))
optalg = ConjugateGradient(; verbosity = 2, maxiter = 10^6, gradtol = 1e-7);
linalg = GMRES(; krylovdim = 256, tol = 1e-9);
eigalg = Arnoldi(; krylovdim = 256, tol = 1e-9);

ΨL2, ρR2, E2, e2 = groundstate(H2, Ψ2; optalg = optalg, linalg = linalg, eigalg = eigalg)

# Free fermion
Q = Constant(randn(D,D))
R = Constant(kron([0 1; 0 0], randn(D>>1,D>>1)))
ΨF = InfiniteCMPS(Q, R)

HF = ∫(∂ψ'*∂ψ - 1 * ψ'*ψ + 1000 * (ψ')^2*ψ^2, (-Inf,+Inf))
ΨL, ρR, E, e = groundstate(H, Ψ; optalg = optalg, linalg = linalg, eigalg = eigalg)


text:
# ------------------------------------------------------------------
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------

"""
   PoissonProcess(λ)

A Poisson process with intensity `λ`.
"""
struct PoissonProcess{L<:Union{Real,Function}} <: PointProcess
  λ::L
end

ishomogeneous(p::PoissonProcess{<:Real}) = true
ishomogeneous(p::PoissonProcess{<:Function}) = false

struct ProductSampling end
struct ThinnedSampling end
struct DiscretizedSampling end

default_sampling_algorithm(::PoissonProcess{<:Real}) = ProductSampling()
default_sampling_algorithm(::PoissonProcess{<:Function}) = DiscretizedSampling()

#------------------
# HOMOGENEOUS CASE
#------------------
function rand_single(p::PoissonProcess{<:Real}, b::Box{Dim,T},
                     ::ProductSampling) where {Dim,T}
  # region configuration
  lo, up = coordinates.(extrema(b))

  # simulate number of points
  λ = p.λ; V = measure(b)
  n = rand(Poisson(λ*V))

  # product of uniform distributions
  U = product_distribution([Uniform(lo[i], up[i]) for i in 1:Dim])

  # return point pattern
  PointSet(rand(U, n))
end

#--------------------
# INHOMOGENEOUS CASE
#--------------------
function rand_single(p::PoissonProcess{<:Function}, g::Box{Dim,T},
                     algo::DiscretizedSampling) where {Dim,T}
  # discretize region
  # TODO

  # discretize retention
  # TODO

  # sample each element
  # TODO
end

function rand_single(p::PoissonProcess{<:Function}, b::Box{Dim,T},
                     algo::ThinnedSampling) where {Dim,T}
  # Lewis-Shedler algorithm
  # TODO
end

Base.union(p₁::PoissonProcess{<:Real}, p₂::PoissonProcess{<:Real}) =
  PoissonProcess(p₁.λ + p₂.λ)

Base.union(p₁::PoissonProcess{<:Function}, p₂::PoissonProcess{<:Function}) =
  PoissonProcess(x -> p₁.λ(x) + p₂.λ(x))

Base.union(p₁::PoissonProcess{<:Real}, p₂::PoissonProcess{<:Function}) =
  PoissonProcess(x -> p₁.λ + p₂.λ(x))

Base.union(p₁::PoissonProcess{<:Function}, p₂::PoissonProcess{<:Real}) =
  PoissonProcess(x -> p₁.λ(x) + p₂.λ)


text:
using SigMF
using Test

@testset "SigMF.jl" begin
    f = SigMF.load("logo/sigmf_logo.sigmf")
    @test typeof(f) == SigMFFile{Base.ReinterpretArray{Int16, 1, UInt8, Vector{UInt8}, false}}

    !isdir("test_save") && mkdir("test_save")
    @test SigMF.save("test_save/sigmf_logo.sigmf", f) == 1152000
end


text:
using Documenter, SymArrays

makedocs(;
    modules=[SymArrays],
    format=Documenter.HTML(),
    pages=[
        "Home" => "index.md",
    ],
    repo="https://github.com/jfeist/SymArrays.jl/blob/{commit}{path}#L{line}",
    sitename="SymArrays.jl",
    authors="Johannes Feist",
    assets=String[],
)

deploydocs(;
    repo="github.com/jfeist/SymArrays.jl",
)


text:
using NearestNeighbors

"""
    initialdensity = estimatedensities(smd::SMD,
        clusterdata::Vector{Matrix{Float32}}, params::ParamStruct)

Estimate local emitter densities for clusters in `smd` and `clusterdata`.

# Description
The initial local densities `initialdensity` around each pre-cluster present in
`smd`/`clusterdata` are estimated based on the local density of pre-clusters
throughout the entire set of data as well as some of the rate parameters
provided in `params`.
"""
function estimatedensities(smd::SMD, clusterdata::Vector{Matrix{Float32}},
    params::ParamStruct)
    # Define some new parameters.
    dutycycle = params.k_on / (params.k_on+params.k_off+params.k_bleach)
    nclusters = length(clusterdata)
    if isempty(smd.nframes)
        maxframe = maximum(smd.framenum)
    else
        maxframe = smd.nframes
    end

    # If only one cluster is present, we should return an answer right away and stop.
    if nclusters == 1
        if size(clusterdata[1], 1) == 1
            initialdensity = 1
        else
            clusterarea = (maximum(clusterdata[1][:, 1])-minimum(clusterdata[1][:, 1])) *
                (maximum(clusterdata[1][:, 1])-minimum(clusterdata[1][:, 1]))
            initialdensity = (1/clusterarea) *
                ((params.k_bleach/params.k_off) / (1-params.p_miss)) /
                (1-exp(-params.k_bleach*dutycycle*(maxframe-1)))
        end
        return initialdensity
    end

    # Determine the center of all clusters assuming each arose from the same
    # emitter.
    clustercenters = zeros(2, nclusters)
    for nn = 1:nclusters
        # Isolate some arrays to improve readability.
        x = clusterdata[nn][:, 1]
        y = clusterdata[nn][:, 2]
        x_se = clusterdata[nn][:, 3]
        y_se = clusterdata[nn][:, 4]

        # Compute the cluster centers based on MLE of position.
        clustercenters[1:2, nn] = [sum(x./x_se.^2) / sum(1 ./ x_se.^2);
            sum(y./y_se.^2) / sum(1 ./ y_se.^2)]
    end

    # Estimate the local cluster density based on the distance to
    # nearest-neighbors.
    kneighbors = minimum([params.nnearestclusters nclusters-1])
    kdtree = KDTree(clustercenters)
    _, nndist = knn(kdtree, clustercenters, kneighbors+1)
    nndist = getindex.(nndist, 1:(kneighbors-1))
    clusterdensity = (kneighbors+1) ./ (pi*nndist.^2)

    # Estimate the density of underlying emitters based on cluster density.
    lambda1 = params.k_bleach * dutycycle
    lambda2 = (params.k_on+params.k_off+params.k_bleach) - lambda1
    initialdensity = clusterdensity *
        (1.0/dutycycle) * (1.0/params.k_off) * (1.0/(1.0-params.p_miss)) ./
        ((1.0/lambda1)*(1.0-exp(-lambda1*(maxframe-1.0))) -
        (1.0/lambda2)*(1.0-exp(-lambda2*(maxframe-1.0))))

    return initialdensity
end


text:
function is_file_path_ok(path_to_file::String)

    if (isfile(path_to_file) == false)
        throw(ArgumentError("$(path_to_file) does not exist."))
    end
end

function is_dir_path_ok(path_to_file::String)

    # get the dir of the path -
    dir_name = dirname(path_to_file)

    # check, is this a legit dir?
    if (isdir(dir_name) == false)
        throw(ArgumentError("$(dir_name) does not exist."))
    end
end

function is_cobra_dictionary_ok(cobra_dictionary::Dict{String,Any})
end

function is_kegg_organism_code_ok(kegg_organism_code::Symbol)
end

max_stars_repo_name: varnerlab/CFMG

max_issues_repo_name: varnerlab/CFMG

max_forks_repo_name: varnerlab/CFMG


text:
# nufft/z-test.jl

using Test: @testset

# nufft/z-list.jl

list = [
"dtft.jl"
"nufft.jl"
]

for file in list
	@testset "$file" begin
		include(file)
	end
end


text:
using RocketBuilder
using Test

@testset "RocketBuilder.jl" begin
    # Write your tests here.
end