text:
using ITensors,
      Test

@testset "Physics Sites" begin

  N = 10

  @testset "Spin Half sites" begin

    s = siteind("S=1/2")
    @test hastags(s,"S=1/2,Site")
    @test dim(s) == 2

    s = siteind("S=1/2"; conserve_qns=true)
    @test hastags(s,"S=1/2,Site")
    @test dim(s) == 2
    @test nblocks(s) == 2
    @test qn(s,1) == QN("Sz",+1)
    @test qn(s,2) == QN("Sz",-1)

    s = siteind("S=1/2"; conserve_szparity = true)
    @test hastags(s, "S=1/2,Site")
    @test dim(s) == 2
    @test nblocks(s) == 2
    @test qn(s,1) == QN("SzParity", 1, 2)
    @test qn(s,2) == QN("SzParity", 0, 2)

    s = siteind("S=1/2"; conserve_sz = true,
                         conserve_szparity = true)
    @test hastags(s, "S=1/2,Site")
    @test dim(s) == 2
    @test nblocks(s) == 2
    @test qn(s,1) == QN(("SzParity", 1, 2), ("Sz", +1))
    @test qn(s,2) == QN(("SzParity", 0, 2), ("Sz", -1))

    s = siteinds("S=1/2", N)
    @test state(s[1],"Up") == s[1](1)
    @test state(s[1],"Dn") == s[1](2)
    @test_throws ArgumentError state(s[1],"Fake")

    Sz5 = op("Sz",s,5)
    @test hasinds(Sz5,s[5]',s[5])

    @test_throws ArgumentError op(s, "Fake", 2)
    @test Array(op("Id",s,3),s[3]',s[3])  ≈ [ 1.0  0.0; 0.0  1.0]
    @test Array(op("F",s,3),s[3]',s[3])   ≈ [ 1.0  0.0; 0.0  1.0]
    @test Array(op("S+",s,3),s[3]',s[3])  ≈ [ 0.0  1.0; 0.0  0.0]
    @test Array(op("S⁺",s,3),s[3]',s[3])  ≈ [ 0.0  1.0; 0.0  0.0]
    @test Array(op("S-",s,4),s[4]',s[4])  ≈ [ 0.0  0.0; 1.0  0.0]
    @test Array(op("S⁻",s,4),s[4]',s[4])  ≈ [ 0.0  0.0; 1.0  0.0]
    @test Array(op("Sx",s,2),s[2]',s[2])  ≈ [ 0.0  0.5; 0.5  0.0]
    @test Array(op("Sˣ",s,2),s[2]',s[2])  ≈ [ 0.0  0.5; 0.5  0.0]
    @test Array(op("iSy",s,2),s[2]',s[2]) ≈ [ 0.0  0.5;-0.5  0.0]
    @test Array(op("iSʸ",s,2),s[2]',s[2]) ≈ [ 0.0  0.5;-0.5  0.0]
    @test Array(op("Sy",s,2),s[2]',s[2])  ≈ [0.0  -0.5im; 0.5im  0.0]
    @test Array(op("Sʸ",s,2),s[2]',s[2])  ≈ [0.0  -0.5im; 0.5im  0.0]
    @test Array(op("Sz",s,2),s[2]',s[2])  ≈ [ 0.5  0.0; 0.0 -0.5]
    @test Array(op("Sᶻ",s,2),s[2]',s[2])  ≈ [ 0.5  0.0; 0.0 -0.5]
    @test Array(op("ProjUp",s,2),s[2]',s[2])  ≈ [ 1.0  0.0; 0.0 0.0]
    @test Array(op("projUp",s,2),s[2]',s[2])  ≈ [ 1.0  0.0; 0.0 0.0]
    @test Array(op("ProjDn",s,2),s[2]',s[2])  ≈ [ 0.0  0.0; 0.0 1.0]
    @test Array(op("projDn",s,2),s[2]',s[2])  ≈ [ 0.0  0.0; 0.0 1.0]
  end

  @testset "Spin One sites" begin
    s = siteinds("S=1",N)

    @test state(s[1],"Up") == s[1](1)
    @test state(s[1],"0")  == s[1](2)
    @test state(s[1],"Dn") == s[1](3)
    @test_throws ArgumentError state(s[1],"Fake")

    Sz5 = op("Sz",s,5)
    @test hasinds(Sz5,s[5]',s[5])

    @test_throws ArgumentError op(s, "Fake", 2)
    @test Array(op("Id",s,3),s[3]',s[3])  ≈ [ 1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0]
    @test Array(op("S+",s,3),s[3]',s[3]) ≈ [ 0 √2 0; 0 0 √2; 0 0 0]
    @test Array(op("S⁺",s,3),s[3]',s[3]) ≈ [ 0 √2 0; 0 0 √2; 0 0 0]
    @test Array(op("S-",s,3),s[3]',s[3]) ≈ [ 0 0 0; √2 0 0; 0.0 √2 0]
    @test Array(op("S⁻",s,3),s[3]',s[3]) ≈ [ 0 0 0; √2 0 0; 0.0 √2 0]
    @test Array(op("Sx",s,3),s[3]',s[3]) ≈ [ 0 1/√2 0; 1/√2 0 1/√2; 0 1/√2 0]
    @test Array(op("Sˣ",s,3),s[3]',s[3]) ≈ [ 0 1/√2 0; 1/√2 0 1/√2; 0 1/√2 0]
    @test Array(op("iSy",s,3),s[3]',s[3]) ≈ [ 0 1/√2 0; -1/√2 0 1/√2; 0 -1/√2 0]
    @test Array(op("iSʸ",s,3),s[3]',s[3]) ≈ [ 0 1/√2 0; -1/√2 0 1/√2; 0 -1/√2 0]
    @test Array(op("Sy",s,3),s[3]',s[3]) ≈ [ 0 -1/√2im 0; +1/√2im 0 -1/√2im; 0 +1/√2im 0]
    @test Array(op("Sʸ",s,3),s[3]',s[3]) ≈ [ 0 -1/√2im 0; +1/√2im 0 -1/√2im; 0 +1/√2im 0]
    @test Array(op("Sz",s,2),s[2]',s[2]) ≈ [1.0 0 0; 0 0 0; 0 0 -1.0]
    @test Array(op("Sᶻ",s,2),s[2]',s[2]) ≈ [1.0 0 0; 0 0 0; 0 0 -1.0]
    @test Array(op("Sz2",s,2),s[2]',s[2]) ≈ [1.0 0 0; 0 0 0; 0 0 +1.0]
    @test Array(op("Sx2",s,2),s[2]',s[2]) ≈ [0.5 0 0.5;0 1.0 0;0.5 0 0.5]
    @test Array(op("Sy2",s,2),s[2]',s[2]) ≈ [0.5 0 -0.5;0 1.0 0;-0.5 0 0.5]
  end

  @testset "Fermion sites" begin
    s = siteind("Fermion")

    @test state(s,"0")   == s(1)
    @test state(s,"1")   == s(2)
    @test_throws ArgumentError state(s,"Fake")

    N = op(s,"N")
    @test hasinds(N,s',s)

    @test_throws ArgumentError op(s, "Fake")
    N = Array(op(s,"N"),s',s)
    @test N ≈ [0. 0; 0 1]
    C = Array(op(s,"C"),s',s)
    @test C ≈ [0. 1; 0 0]
    Cdag = Array(op(s,"Cdag"),s',s)
    @test Cdag ≈ [0. 0; 1 0]
    F = Array(op(s,"F"),s',s)
    @test F ≈ [1. 0; 0 -1]

    @test has_fermion_string("C", s)
    @test has_fermion_string("Cdag", s)
    @test has_fermion_string("C*F", s)
    @test has_fermion_string("F*Cdag*F", s)
    @test !has_fermion_string("N", s)
    @test !has_fermion_string("N*F", s)

    s = siteind("Fermion";conserve_nf=true)
    @test qn(s,1) == QN("Nf",0,-1)
    @test qn(s,2) == QN("Nf",1,-1)
    s = siteind("Fermion";conserve_nfparity=true)
    @test qn(s,1) == QN("NfParity",0,-2)
    @test qn(s,2) == QN("NfParity",1,-2)
    s = siteind("Fermion";conserve_qns=false)
    @test dim(s) == 2

    s = siteind("Fermion";conserve_nf=true, conserve_sz=true)
    @test qn(s,1) == QN(("Nf",0,-1),("Sz",0))
    @test qn(s,2) == QN(("Nf",1,-1),("Sz",1))
    s = siteind("Fermion";conserve_nfparity=true, conserve_sz=true)
    @test qn(s,1) == QN(("NfParity",0,-2),("Sz",0))
    @test qn(s,2) == QN(("NfParity",1,-2),("Sz",1))
    s = siteind("Fermion";conserve_nf=true, conserve_sz="Up")
    @test qn(s,1) == QN(("Nf",0,-1),("Sz",0))
    @test qn(s,2) == QN(("Nf",1,-1),("Sz",1))
    s = siteind("Fermion";conserve_nfparity=true, conserve_sz="Up")
    @test qn(s,1) == QN(("NfParity",0,-2),("Sz",0))
    @test qn(s,2) == QN(("NfParity",1,-2),("Sz",1))
    s = siteind("Fermion";conserve_nf=true, conserve_sz="Dn")
    @test qn(s,1) == QN(("Nf",0,-1),("Sz",0))
    @test qn(s,2) == QN(("Nf",1,-1),("Sz",-1))
    s = siteind("Fermion";conserve_nfparity=true, conserve_sz="Dn")
    @test qn(s,1) == QN(("NfParity",0,-2),("Sz",0))
    @test qn(s,2) == QN(("NfParity",1,-2),("Sz",-1))
  end

  @testset "Electron sites" begin
    s = siteind("Electron")

    @test state(s,"0")    == s(1)
    @test state(s,"Up")   == s(2)
    @test state(s,"Dn")   == s(3)
    @test state(s,"UpDn") == s(4)
    @test_throws ArgumentError state(s,"Fake")

    Nup = op(s,"Nup")
    @test hasinds(Nup,s',s)

    @test_throws ArgumentError op(s, "Fake")
    Nup = Array(op(s,"Nup"),s',s)
    @test Nup ≈ [0. 0 0 0; 0 1 0 0; 0 0 0 0; 0 0 0 1]
    Ndn = Array(op(s,"Ndn"),s',s)
    @test Ndn ≈ [0. 0 0 0; 0 0 0 0; 0 0 1 0; 0 0 0 1]
    Ntot = Array(op(s,"Ntot"),s',s)
    @test Ntot ≈ [0. 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 2]
    Cup = Array(op(s,"Cup"),s',s)
    @test Cup ≈ [0. 1 0 0; 0 0 0 0; 0 0 0 1; 0 0 0 0]
    Cdagup = Array(op(s,"Cdagup"),s',s)
    @test Cdagup ≈ [0. 0 0 0; 1 0 0 0; 0 0 0 0; 0 0 1 0]
    Cdn = Array(op(s,"Cdn"),s',s)
    @test Cdn ≈ [0. 0 1 0; 0 0 0 -1; 0 0 0 0; 0 0 0 0]
    Cdagdn = Array(op(s,"Cdagdn"),s',s)
    @test Cdagdn ≈ [0. 0 0 0; 0 0 0 0; 1 0 0 0; 0 -1 0 0]
    F = Array(op(s,"F"),s',s)
    @test F ≈ [1. 0 0 0; 0 -1 0 0; 0 0 -1 0; 0 0 0 1]
    Fup = Array(op(s,"Fup"),s',s)
    @test Fup ≈ [1. 0 0 0; 0 -1 0 0; 0 0 1 0; 0 0 0 -1]
    Fdn3 = Array(op(s,"Fdn"),s',s)
    @test Fdn3 ≈ [1. 0 0 0; 0 1 0 0; 0 0 -1 0; 0 0 0 -1]
    Sz3 = Array(op(s,"Sz"),s',s)
    @test Sz3 ≈ [0. 0 0 0; 0 0.5 0 0; 0 0 -0.5 0; 0 0 0 0]
    Sx3 = Array(op(s,"Sx"),s',s)
    @test Sx3 ≈ [0. 0 0 0; 0 0 0.5 0; 0 0.5 0 0; 0 0 0 0]
    Sp3 = Array(op(s,"S+"),s',s)
    @test Sp3 ≈ [0. 0 0 0; 0 0 1 0; 0 0 0 0; 0 0 0 0]
    Sm3 = Array(op(s,"S-"),s',s)
    @test Sm3 ≈ [0. 0 0 0; 0 0 0 0; 0 1 0 0; 0 0 0 0]

    @test has_fermion_string("Cup", s)
    @test has_fermion_string("Cup*F", s)
    @test has_fermion_string("Cdagup", s)
    @test has_fermion_string("F*Cdagup", s)
    @test has_fermion_string("Cdn", s)
    @test has_fermion_string("Cdn*F", s)
    @test has_fermion_string("Cdagdn", s)
    @test !has_fermion_string("N", s)
    @test !has_fermion_string("F*N", s)

    s = siteind("Electron";conserve_nf=true)
    @test qn(s,1) == QN("Nf",0,-1)
    @test qn(s,2) == QN("Nf",1,-1)
    @test qn(s,3) == QN("Nf",2,-1)
    s = siteind("Electron";conserve_sz=true)
    @test qn(s,1) == QN(("Sz", 0),("NfParity",0,-2))
    @test qn(s,2) == QN(("Sz",+1),("NfParity",1,-2))
    @test qn(s,3) == QN(("Sz",-1),("NfParity",1,-2))
    @test qn(s,4) == QN(("Sz", 0),("NfParity",0,-2))
    s = siteind("Electron";conserve_nfparity=true)
    @test qn(s,1) == QN("NfParity",0,-2)
    @test qn(s,2) == QN("NfParity",1,-2)
    @test qn(s,3) == QN("NfParity",0,-2)
    s = siteind("Electron";conserve_qns=false)
    @test dim(s) == 4
  end

  @testset "tJ sites" begin
    s = siteind("tJ")

    @test state(s,"0")    == s(1)
    @test state(s,"Up")   == s(2)
    @test state(s,"Dn")   == s(3)
    @test_throws ArgumentError state(s,"Fake")

    @test_throws ArgumentError op(s, "Fake")
    Nup = op(s,"Nup")
    @test Nup[2,2] ≈ 1.0
    Ndn = op(s,"Ndn")
    @test Ndn[3,3] ≈ 1.0
    Ntot = op(s,"Ntot")
    @test Ntot[2,2] ≈ 1.0
    @test Ntot[3,3] ≈ 1.0
    Id = Array(op(s,"Id"),s',s)
    @test Id ≈ [1.0 0 0; 0 1 0; 0 0 1]
    Cup = Array(op(s,"Cup"),s',s)
    @test Cup ≈ [0. 1 0; 0 0 0; 0 0 0]
    Cdup = Array(op(s,"Cdagup"),s',s)
    @test Cdup ≈ [0 0 0; 1. 0 0; 0 0 0]
    Cdn = Array(op(s,"Cdn"),s',s)
    @test Cdn ≈ [0. 0. 1; 0 0 0; 0 0 0]
    Cddn = Array(op(s,"Cdagdn"),s',s)
    @test Cddn ≈ [0 0 0; 0. 0 0; 1 0 0]
    FP = Array(op(s,"F"),s',s)
    @test FP ≈ [1.0 0. 0; 0 -1.0 0; 0 0 -1.0]
    Fup = Array(op(s,"Fup"),s',s)
    @test Fup ≈ [1.0 0. 0; 0 -1.0 0; 0 0 1.0]
    Fdn = Array(op(s,"Fdn"),s',s)
    @test Fdn ≈ [1.0 0. 0; 0 1.0 0; 0 0 -1.0]
    Sz = Array(op(s,"Sz"),s',s)
    @test Sz ≈ [0.0 0. 0; 0 0.5 0; 0 0 -0.5]
    Sx = Array(op(s,"Sx"),s',s)
    @test Sx ≈ [0.0 0. 0; 0 0 0.5; 0 0.5 0]
    Sp = Array(op(s,"Splus"),s',s)
    @test Sp ≈ [0.0 0. 0; 0 0 1.0; 0 0 0]
    Sm = Array(op(s,"Sminus"),s',s)
    @test Sm ≈ [0.0 0. 0; 0 0 0; 0 1.0 0]

    @test has_fermion_string("Cup", s)
    @test has_fermion_string("Cdagup", s)
    @test has_fermion_string("Cdn", s)
    @test has_fermion_string("Cdagdn", s)
    @test !has_fermion_string("N", s)
  end

end

nothing


text:
module FrostHelperWASDMovementTrigger

using ..Ahorn, Maple

@mapdef Trigger "FrostHelper/WASDMovementTrigger" WASDMovementTrigger(x::Integer, y::Integer, width::Integer=16, height::Integer=16, hitboxWidth::Integer=2, speed::Number=80.0, texture::String="util/pixel")

const placements = Ahorn.PlacementDict(
	"WASD Movement (Frost Helper)" => Ahorn.EntityPlacement(
		WASDMovementTrigger,
		"rectangle"
	)
)

end

ext: jl

max_stars_repo_name: JaThePlayer/FrostHelper

max_issues_repo_name: JaThePlayer/FrostHelper

max_forks_repo_name: JaThePlayer/FrostHelper


text:
# using Plots; pyplot(); x = linspace(-2,2,20); y = linspace(-1,3,20); contourf(x, y, rosenbrock, zlim=(0,1000))
#
# julia> xy = vec([(xi,yi) for xi=x,yi=y]);
#
# julia> uv = map(xyi -> (g=rosenbrock_gradient(collect(xyi))/2000; (g[1],g[2])), xy);
#
# julia> quiver!(Plots.unzip(xy)..., quiver=uv, c=:cyan, alpha=0.4)
#
# julia> uv = map(xyi -> (g=rosenbrock_gradient(collect(xyi))/-2000; (g[1],g[2])), xy);

using Plots; begin
pyplot()
x = linspace(-2,2,20)
y = linspace(-1,3,20)
xy = vec([(xi,yi) for xi=x,yi=y])
uv = map(xyi -> (g=rosenbrock_gradient(collect(xyi))/-2000; (g[1],g[2])), xy)
contourf(x, y, rosenbrock, xlim=extrema(x), ylim=extrema(y))
quiver!(Plots.unzip(xy)..., quiver=uv, c=:cyan, alpha=0.4)
end


text:
### ARITHMETIC OPERATIONS

function mul!(output::Union{Tuple{AbstractVector{T},AbstractVector{T}},AbstractVectorOfArray{T}},sys::SaddleSystem{T,Ns,Nc},
  input::Union{Tuple{AbstractVector{T},AbstractVector{T}},AbstractVectorOfArray{T}}) where {T,Ns,Nc}

    @unpack A, B₂, B₁ᵀ, C = sys

    u,f = input
    r₁,r₂ = output
    length(u) == length(r₁) == Ns || error("Incompatible number of elements")
    length(f) == length(r₂) == Nc || error("Incompatible number of elements")

    r₁ .= A*u .+ B₁ᵀ*f
    r₂ .= B₂*u .+ C*f
    return output
end

function mul!(sol::Tuple{TU,TF},sys::SaddleSystem,rhs::Tuple{TU,TF}) where {T,Ns,Nc,TU,TF}
    u, f = sol
    r₁, r₂ = rhs
    return mul!((_unwrap_vec(u),_unwrap_vec(f)),sys,(_unwrap_vec(r₁),_unwrap_vec(r₂)))
end

function mul!(sol::ArrayPartition,sys::SaddleSystem,rhs::ArrayPartition) where {T,Ns,Nc,TU,TF}
    u, f = sol.x
    r₁, r₂ = rhs.x
    return mul!((_unwrap_vec(u),_unwrap_vec(f)),sys,(_unwrap_vec(r₁),_unwrap_vec(r₂)))
end

function (*)(sys::SaddleSystem,input::Tuple)
    u, f = input
    output = (similar(u),similar(f))
    mul!(output,sys,input)
    return output
end

# Routine for accepting vector inputs, parsing it into Ns and Nc parts
function mul!(sol::AbstractVector{T},sys::SaddleSystem{T,Ns,Nc},rhs::AbstractVector{T}) where {T,Ns,Nc}
    mul!(_split_vector(sol,Ns,Nc),sys,_split_vector(rhs,Ns,Nc))
    return sol
end

function (*)(sys::SaddleSystem{T},rhs::Union{AbstractVector{T},AbstractVectorOfArray{T},ArrayPartition{T}}) where {T}
    output = similar(rhs)
    mul!(output,sys,rhs)
    return output
end

## Multiplying tuples of saddle point systems

function mul!(sol,sys::NTuple{M,SaddleSystem},rhs) where {M}
   for (i,sysi) in enumerate(sys)
     mul!(sol[i],sysi,rhs[i])
   end
   sol
end

function (*)(sys::NTuple{M,SaddleSystem},rhs) where {M}
    sol = deepcopy.(rhs)
    mul!(sol,sys,rhs)
    return sol
end

#### Left division ####

function ldiv!(sol::Union{Tuple{AbstractVector{T},AbstractVector{T}},AbstractVectorOfArray{T}},sys::SaddleSystem{T,Ns,Nc},
              rhs::Union{Tuple{AbstractVector{T},AbstractVector{T}},AbstractVectorOfArray{T}}) where {T,Ns,Nc}
    @unpack A⁻¹, B₂, B₁ᵀ, B₂A⁻¹r₁, P, S⁻¹, _f_buf, A⁻¹B₁ᵀf = sys

    N = Ns+Nc
    u,f = sol
    r₁,r₂ = rhs
    length(u) == length(r₁) == Ns || error("Incompatible number of elements")
    length(f) == length(r₂) == Nc || error("Incompatible number of elements")

    u .= A⁻¹*r₁

    B₂A⁻¹r₁ .= B₂*u
    _f_buf .= r₂
    _f_buf .-= B₂A⁻¹r₁

    if Nc > 0
        f .= S⁻¹*_f_buf
        f .= P*f
    end
    A⁻¹B₁ᵀf .= A⁻¹*B₁ᵀ*f
    u .-= A⁻¹B₁ᵀf

    return sol
end

function ldiv!(sol::Tuple{TU,TF},sys::SaddleSystem,rhs::Tuple{TU,TF}) where {T,Ns,Nc,TU,TF}
    u, f = sol
    r₁, r₂ = rhs
    return ldiv!((_unwrap_vec(u),_unwrap_vec(f)),sys,(_unwrap_vec(r₁),_unwrap_vec(r₂)))
end

function ldiv!(sol::ArrayPartition,sys::SaddleSystem,rhs::ArrayPartition) where {T,Ns,Nc,TU,TF}
    u, f = sol.x
    r₁, r₂ = rhs.x
    return ldiv!((_unwrap_vec(u),_unwrap_vec(f)),sys,(_unwrap_vec(r₁),_unwrap_vec(r₂)))
end

function (\)(sys::SaddleSystem,rhs::Tuple) where {T,Ns,Nc}
    u, f = rhs
    sol = (similar(u),similar(f))
    ldiv!(sol,sys,rhs)
    return sol
end

# Routine for accepting vector inputs, parsing it into Ns and Nc parts
function ldiv!(sol::AbstractVector{T},sys::SaddleSystem{T,Ns,Nc},rhs::AbstractVector{T}) where {T,Ns,Nc}
    ldiv!(_split_vector(sol,Ns,Nc),sys,_split_vector(rhs,Ns,Nc))
    return sol
end

function (\)(sys::SaddleSystem{T},rhs::Union{AbstractVector{T},AbstractVectorOfArray{T},ArrayPartition{T}}) where {T}
    sol = similar(rhs)
    ldiv!(sol,sys,rhs)
    return sol
end

## Solving tuples of saddle point systems

function ldiv!(sol,sys::NTuple{M,SaddleSystem},rhs) where {M}
   for (i,sysi) in enumerate(sys)
     ldiv!(sol[i],sysi,rhs[i])
   end
   sol
end

function (\)(sys::NTuple{M,SaddleSystem},rhs) where {M}
    sol = deepcopy.(rhs)
    ldiv!(sol,sys,rhs)
    return sol
end

# vector -> tuple
_split_vector(x,Ns,Nc) = view(x,1:Ns), view(x,Ns+1:Ns+Nc)


text:
using JLLWrappers
using Pkg
using Test

module TestJLL end

@testset "JLLWrappers.jl" begin
    mktempdir() do dir
        Pkg.activate(dir)
        # Package with a FileProduct
        Pkg.develop(PackageSpec(path=joinpath(@__DIR__, "Vulkan_Headers_jll")))
        @test_nowarn @eval TestJLL using Vulkan_Headers_jll
        @test @eval TestJLL Vulkan_Headers_jll.is_available()
        @test isfile(@eval TestJLL vk_xml)
        # Package with an ExecutableProduct
        Pkg.develop(PackageSpec(path=joinpath(@__DIR__, "HelloWorldC_jll")))
        @test_nowarn @eval TestJLL using HelloWorldC_jll
        @test @eval TestJLL HelloWorldC_jll.is_available()
        @test "Hello, World!" == @eval TestJLL hello_world(h->readchomp(`$h`))
        # Package with a LibraryProduct
        Pkg.develop(PackageSpec(path=joinpath(@__DIR__, "OpenLibm_jll")))
        @test_nowarn @eval TestJLL using OpenLibm_jll
        @test @eval TestJLL OpenLibm_jll.is_available()
        @test exp(3.14) ≈ @eval TestJLL ccall((:exp, libopenlibm), Cdouble, (Cdouble,), 3.14)
    end
end


text:
names(::Type{NamedTuple{nms, T}}) where {nms, T} = nms
types(::Type{NamedTuple{nms, T}}) where {nms, T} = T

"helper function to calculate a run-length encoding of a tuple type"
Base.@pure function runlength(::Type{T}) where {T <: Tuple}
    rle = Tuple{Type, Int}[]
    fieldcount(T) == 0 && return rle
    curT = fieldtype(T, 1)
    prevT = curT
    len = 1
    for i = 2:fieldcount(T)
        @inbounds curT = fieldtype(T, i)
        if curT === prevT
            len += 1
        else
            push!(rle, (prevT, len))
            prevT = curT
            len = 1
        end
    end
    push!(rle, (curT, len))
    return rle
end

# generic fallback from getproperty w/ type information to basic symbol lookup
Base.getproperty(x, ::Type{T}, i::Int, nm) where {T} = getproperty(x, nm)
Base.getproperty(x::NamedTuple{names, types}, ::Type{T}, i::Int, nm::Symbol) where {names, types, T} = Core.getfield(x, i)

"""
    Tables.eachcolumn(f, sch, row, args...)
    Tables.eachcolumn(Tables.columns(x))

    The first definition takes a function `f`, table schema `sch`, a `row` type (that satisfies the `Tables.Row` interface), and any other `args...`;
    it generates calls to get the value for each column in the row (`getproperty(row, nm)`) and then calls `f(val, col, name, args...)`, where `f` is the
    user-provided function, `val` is a row's column value, `col` is the column index as an `Int`, and `name` is the row's column name as a `Symbol`.

    While the first definition applies to a `Row` object, the last definition simply returns a property-iterator over a `Columns` object.
    For example, one could "collect" every column of a `Columns` object by doing:
    ```julia
    vectors = [collect(col) for col in Tables.eachcolumn(Tables.columns(x))]
    ```
"""
function eachcolumn end

quot(s::Symbol) = Meta.QuoteNode(s)
quot(x::Int) = x

@inline function eachcolumn(f::Base.Callable, sch::Schema{names, types}, row, args...) where {names, types}
    if @generated
        if length(names) < 101
            block = Expr(:block, Expr(:meta, :inline))
            for i = 1:length(names)
                push!(block.args, quote
                    f(getproperty(row, $(fieldtype(types, i)), $i, $(quot(names[i]))), $i, $(quot(names[i])), args...)
                end)
            end
            return block
        end
        rle = runlength(types)
        if length(rle) < 100
            block = Expr(:block, Expr(:meta, :inline))
            i = 1
            for (T, len) in rle
                push!(block.args, quote
                    for j = 0:$(len-1)
                        @inbounds f(getproperty(row, $T, $i + j, names[$i + j]), $i + j, names[$i + j], args...)
                    end
                end)
                i += len
            end
            b = block
        else
            b = quote
                $(Expr(:meta, :inline))
                for (i, nm) in enumerate(names)
                    f(getproperty(row, fieldtype(types, i), i, nm), i, nm, args...)
                end
                return
            end
        end
        # println(b)
        return b
    else
        for (i, nm) in enumerate(names)
            f(getproperty(row, fieldtype(types, i), i, nm), i, nm, args...)
        end
        return
    end
end

@inline function eachcolumn(f::Base.Callable, sch::Schema{names, nothing}, row, args...) where {names}
    if @generated
        if length(names) < 100
            block = Expr(:block, Expr(:meta, :inline))
            for i = 1:length(names)
                push!(block.args, quote
                    f(getproperty(row, $(quot(names[i]))), $i, $(quot(names[i])), args...)
                end)
            end
            return block
        else
            b = quote
                $(Expr(:meta, :inline))
                for (i, nm) in enumerate(names)
                    f(getproperty(row, nm), i, nm, args...)
                end
                return
            end
            return b
        end
    else
        for (i, nm) in enumerate(names)
            f(getproperty(row, nm), i, nm, args...)
        end
        return
    end
end

# this are specialized `eachcolumn`s where we also want
# the indexing of `columns` to be constant propagated, so it needs to be returned from the generated function
@inline function eachcolumns(f::Base.Callable, sch::Schema{names, types}, row, columns, args...) where {names, types}
    if @generated
        if length(names) < 101
            block = Expr(:block, Expr(:meta, :inline))
            for i = 1:length(names)
                push!(block.args, quote
                    f(getproperty(row, $(fieldtype(types, i)), $i, $(quot(names[i]))), $i, $(quot(names[i])), columns[$i], args...)
                end)
            end
            return block
        end
        rle = runlength(types)
        if length(rle) < 100
            block = Expr(:block, Expr(:meta, :inline))
            i = 1
            for (T, len) in rle
                push!(block.args, quote
                    for j = 0:$(len-1)
                        @inbounds f(getproperty(row, $T, $i + j, names[$i + j]), $i + j, names[$i + j], columns[$i + j], args...)
                    end
                end)
                i += len
            end
            b = block
        else
            b = quote
                $(Expr(:meta, :inline))
                for (i, nm) in enumerate(names)
                    f(getproperty(row, fieldtype(types, i), i, nm), i, nm, columns[i], args...)
                end
                return
            end
        end
        # println(b)
        return b
    else
        for (i, nm) in enumerate(names)
            f(getproperty(row, fieldtype(types, i), i, nm), i, nm, columns[i], args...)
        end
        return
    end
end

@inline function eachcolumns(f::Base.Callable, sch::Schema{names, nothing}, row, columns, args...) where {names}
    if @generated
        if length(names) < 100
            block = Expr(:block, Expr(:meta, :inline))
            for i = 1:length(names)
                push!(block.args, quote
                    f(getproperty(row, $(quot(names[i]))), $i, $(quot(names[i])), columns[$i], args...)
                end)
            end
            return block
        else
            b = quote
                $(Expr(:meta, :inline))
                for (i, nm) in enumerate(names)
                    f(getproperty(row, nm), i, nm, columns[i], args...)
                end
                return
            end
            return b
        end
    else
        for (i, nm) in enumerate(names)
            f(getproperty(row, nm), i, nm, columns[i], args...)
        end
        return
    end
end

# iterator over a `Columns`' properties
struct EachColumn{T}
    source::T
end

Base.length(e::EachColumn) = length(propertynames(e.source))
Base.IteratorEltype(::Type{<:EachColumn}) = Base.EltypeUnknown()

function Base.iterate(e::EachColumn, (idx, props)=(1, propertynames(e.source)))
    idx > length(props) && return nothing
    return getproperty(e.source, props[idx]), (idx + 1, props)
end

eachcolumn(c) = EachColumn(c)

"given names and a Symbol `name`, compute the index (1-based) of the name in names"
Base.@pure function columnindex(names::Tuple{Vararg{Symbol}}, name::Symbol)
    i = 1
    for nm in names
        nm === name && return i
        i += 1
    end
    return 0
end

Base.@pure columntype(::Schema{names, types}, name::Symbol) where {names, types} = columntype(names, types, name)

"given tuple type and a Symbol `name`, compute the type of the name in the tuples types"
Base.@pure function columntype(names::Tuple{Vararg{Symbol}}, ::Type{T}, name::Symbol) where {T <: Tuple}
    i = 1
    for nm in names
        nm === name && return fieldtype(T, i)
        i += 1
    end
    return Union{}
end


text:
wav = 5*randn(32,1);
new = onlineagc(wav); # deepcopy wav and then operate in-place
onlineagc!(wav)       # in-place operation

# if the streaming wav is done. Just reset the online agc params by
setagc()

# also you can re-specify the params by
setagc(gain=1.0, maxvalue=0.6, minstep=-0.6)

max_stars_repo_name: sonosole/AGC

max_issues_repo_name: sonosole/AutoGainCtrl

max_forks_repo_name: sonosole/AutoGainCtrl


text:
#=
This julia script converts fortran 90 code into julia.
It uses naive regex replacements to do as much as possible,
but the output WILL need further cleanup.

Known conversion problems such as GOTO are commented and marked with FIXME

Most variable declaration lines are entirely deleted, which may or
may not be useful.

To run from a shell:

julia fortran-julia.jl filename.f90

Output is written to filename.jl.
=#

using DataStructures

# Regex/substitution pairs for replace(). Order matters here.
replacements = OrderedDict(
  # Lowercase everything not commented
  r"^(?!.*!).*"m => lowercase,
  # Lowercase start of lines with comments
  r"^.*!"m => lowercase,
  # Remove '&' multiline continuations
  r"\s*&\s*" => "",
  # Comments use # not !
  "!" => "#",
  # Powers use ^ not **
  "**" => "^",
  # Only double quotes allowed for strings
  "'" => "\"",
  # DO loop to for loop
  r"do (.*),(.*)" => s"for \1:\2",
  # Spaces around math operators
  r"([\*\+\/=])(?=\S)" => s"\1 ",
  r"(?<=\S)([\*\+\/=])" => s" \1",
  # Spaces around - operators, except after e
  # r"([^e][\-])(\S)" => s"\1 \2",
  r"(?<!\W\de)(\h*\-\h*)" => s" - ",
  # Space after all commas
  r"(,)(\S)" => s"\1 \2",
  # Replace ELSEIF/ELSE IF with elseif
  r"(\s+)else if" => s"\1elseif",
  # Replace IF followed by ( to if (
  r"(\s+)(elseif|if)\(" => s"\1\2 (",
  # Remove THEN
  r"([)\s])then(\s+)" => s"\1\2",
  # Relace END XXXX with end
  r"(\s+)end\h*.*" => s"\1end",
  # Replace expnent function
  r"(\W)exp\(" => s"\1exp(",
  # Reorganise functions and doc strings. This may be very project specific.
  r"#\^\^+\s*subroutine\s*(\w+)([^)]+\))\s*(.*?)#\^\^\^+"sm =>
      Base.SubstitutionString("\"\"\"\n\\3\"\"\"\nfunction \\1\\2::Void"),
  r"\#\^\^+\s*real function\s*(\w+)([^)]+\))\s*(.*?)\#\^\^\^+"sm =>
      Base.SubstitutionString("\"\"\"\n\\3\"\"\"\nfunction \\1\\2::Float64"),
  # Don't need CALL
  r"(\s*)call(\h+)" => s"\1",
  # Use real math symbols
  "gamma" => "Γ",
  "theta" => "Θ",
  "epsilon" => "ϵ",
  "lambda" => "λ",
  "alpha" => "α",
  # Swap logical symbols
  ".true." => "true",
  ".false." => "false",
  r"\s*\.or\.\s*" => " || ",
  r"\s*\.and\.\s*" => " && ",
  r"\s*\.not\.\s*" => " ! ",
  r"\s*\.eq\.\s*" => " == ",
  r"\s*\.ne\.\s*" => " != ",
  r"\s*\.le\.\s*" => " <= ",
  r"\s*\.ge\.\s*" => " >= ",
  r"\s*\.gt\.\s*" => " > ",
  r"\s*\.lt\.\s*" => " < ",
  # Remove (expression) brackets after if
  # r"if \((.*)\)(\s*\n)" => s"if \1\2",
  # Add end after single line if with an = assignment
  r"if\s*(.*?) = (.*?)(\n)" => s"if \1 = \2 end\3",
  # Format floats as "5.0" not "5."
  r"(\W\d+)\.(\D)" => s"\1.0\2",
  # Tab to 4 spaces
  r"\t" => "    ",
  # Relace suberror with error and mark for fixup
  r"(\W)suberror\((.*?),.*?\)" => s"\1 error(\2)",
  # Mark #FIXME the various things this script can't handle
  r"(write|goto|while\s)" => s"#FIXME \1",
)

# Patterns to remove
removal = OrderedDict(
  # Trailing whitespace
  r"\h*$"m => "",
  # Variable declarations
  r"\n\s*real\s.*" => "",
  r"\n\s*real, external\s.*" => "",
  r"\n\s*integer\s.*" => "",
  r"\n\s*implicit none" => "",
  r"\n\s*logical\s.*" => "",
  # Import statements
  r"\n\s*use\s.*" => "",
)

# Load the file from the first command line argument
filename = string(ARGS[1])
code = read(filename, String)

# Process replacements and removals.
for f in replacements
  global code = replace(code, f)
end
for r in removal
  global code = replace(code, r)
end
println(code)

# Write the output to a .jl file with the same filename stem.
stem = split(filename, ".")[1]
outfile = stem * ".jl"
write(outfile, code)

max_stars_repo_name: charlesll/gcvspl

max_issues_repo_name: charlesll/gcvspl

max_forks_repo_name: charlesll/gcvspl


text:
using Base.Collections
import Base.Order: ForwardOrdering

export  num_remotes, prep_remotes,
        execute_worker_task, queue_worker_task, dequeue_worker_task, set_priorities,
        WorkerTask, QueuedWorkerTask

safe_dequeue!(pq::PriorityQueue, key) = try dequeue!(pq,key) end

typealias FuncNone  Union(Function,Nothing)

##n account of the worker machines available
const _remotes = Array(Vector{ASCIIString},0)
const _all_remote_names = Set{String}()
num_remotes() = length(_remotes[1])
function prep_remotes(force::Bool=false)
    !force && (0 != length(_remotes)) && return
    empty!(_remotes)
    empty!(_all_remote_names)

    n = nprocs()
    ips = Array(ASCIIString, n-1)
    hns = Array(ASCIIString, n-1)
    for midx in 2:n
        ips[midx-1] = string(remotecall_fetch(midx, getipaddr))
        hns[midx-1] = string(remotecall_fetch(midx, gethostname))
    end

    for x in (ips, hns)
        push!(_remotes, x)
        union!(_all_remote_names, x)
        unshift!(x, "")     # to represent the default worker node
    end
end

# Worker task type. One of: map, file_info, reduce(in future)
# target can be:
#   - proc id, or a list of procids
#   - machine ip/hostname, or a list of ips/hostnames
#   - :wrkr_all, :wrkr_any
abstract WorkerTask
type QueuedWorkerTask
    wtask::WorkerTask
    remote_method::Function
    callback::FuncNone
    target::Union(Int,ASCIIString,Symbol,Vector{ASCIIString},Vector{Int})
    qtime::Float64
    function QueuedWorkerTask(wtask::WorkerTask, remote_method::Function, callback::FuncNone, target::Union(Int,ASCIIString,Symbol,Vector{ASCIIString},Vector{Int}))
        new(wtask, remote_method, callback, target, time())
    end
end

# Queues for distributing tasks
# TODO: use priorityqueues

const PQTYPE = VERSION < v"0.4-" ? PriorityQueue{QueuedWorkerTask,Float64} : PriorityQueue{QueuedWorkerTask,Float64, ForwardOrdering}
if VERSION < v"0.4-"
    emptypq() = PriorityQueue{QueuedWorkerTask,Float64}()
else
    emptypq() = PriorityQueue(QueuedWorkerTask,Float64)
end

const _machine_tasks = Dict{ASCIIString, PQTYPE}()
const _procid_tasks = Dict{Int, PQTYPE}()
const _any_tasks = emptypq()

function _remap_macs_to_procs(macs)
    available_macs = filter(x->(x in _all_remote_names), macs)
    (length(available_macs) == 0) && (available_macs = filter(x->(x in _all_remote_names), map(x->split(x,".")[1], macs)))
    (length(available_macs) == 0) && push!(available_macs, "")
    available_macs
end

function execute_worker_task(t::QueuedWorkerTask)
    r = RemoteRef()
    function cb(w::WorkerTask, ret)
        put!(r, ret)
    end
    t.callback = cb
    queue_worker_task(t)
    result = fetch(r)
    isa(result, Exception) && throw(result)
    result
end

function queue_worker_task(t::QueuedWorkerTask)
    _queue_worker_task(t, t.target)
    _start_feeders()
end
function _queue_worker_task(t::QueuedWorkerTask, procid::Int)
    !haskey(_procid_tasks, procid) && (_procid_tasks[procid] = emptypq())
    (_procid_tasks[procid])[t] = Inf
end
_queue_worker_task(t::QueuedWorkerTask, procid_list::Vector{Int}) = for procid in procid_list _queue_worker_task(t, procid) end
function _queue_worker_task(t::QueuedWorkerTask, machine::ASCIIString)
    !haskey(_machine_tasks, machine) && (_machine_tasks[machine] = emptypq())
    (_machine_tasks[machine])[t] = Inf
end
_queue_worker_task(t::QueuedWorkerTask, machine_list::Vector{ASCIIString}) = for machine in _remap_macs_to_procs(machine_list) _queue_worker_task(t, machine) end
function _queue_worker_task(t::QueuedWorkerTask, s::Symbol)
    (:wrkr_all == s) && return _queue_worker_task(t::QueuedWorkerTask, [1:num_remotes()])
    (:wrkr_any == s) && return (_any_tasks[t] = Inf)
    error("unknown queue $(s)")
end

dequeue_worker_task(t::QueuedWorkerTask) = _dequeue_worker_task(t::QueuedWorkerTask, t.target)
_dequeue_worker_task(t::QueuedWorkerTask, procid::Int) = haskey(_procid_tasks, procid) && safe_dequeue!(_procid_tasks[procid], t)
_dequeue_worker_task(t::QueuedWorkerTask, procid_list::Vector{Int}) = for procid in procid_list _dequeue_worker_task(t, procid) end
_dequeue_worker_task(t::QueuedWorkerTask, machine::ASCIIString) = haskey(_machine_tasks, machine) && safe_dequeue!(_machine_tasks[machine], t)
_dequeue_worker_task(t::QueuedWorkerTask, machine_list::Vector{ASCIIString}) = for machine in _remap_macs_to_procs(machine_list) _dequeue_worker_task(t, machine) end
function _dequeue_worker_task(t::QueuedWorkerTask, s::Symbol)
    (:wrkr_all == s) && return _dequeue_worker_task(t, [1:num_remotes()])
    (:wrkr_any == s) && return safe_dequeue!(_any_tasks, t)
    error("unknown queue $(s)")
end
function dequeue_worker_task(filter_fn::Function)
    del_set = Set{QueuedWorkerTask}()

    function filter_from(pq)
        for (k1,v1) in pq
            !filter_fn(k1) && add!(del_set, k1)
        end
    end

    for (_,v) in _machine_tasks filter_from(v) end
    for (_,v) in _procid_tasks filter_from(v) end
    filter_from(_any_tasks)
    for dt in del_set dequeue_worker_task(dt) end
end

##
# scheduler function
function set_priorities(calc_prio::Function)
    for (k,v) in _machine_tasks for (k1,v1) in v v[k1] = calc_prio(k, k1, v1) end end
    for (k,v) in _procid_tasks for (k1,v1) in v v[k1] = calc_prio(k, k1, v1) end end
    for (k1, v1) in _any_tasks _any_tasks[k1] = calc_prio(:wrkr_any, k1, v1) end
end

const _feeders = Dict{Int,Task}()
function _start_feeders()
    _debug && println("starting feeders...")
    # start feeder tasks if required
    for procid in 1:num_remotes()
        haskey(_feeders, procid) && !istaskdone(_feeders[procid]) && continue
        ip, hn = map(x->x[procid], _remotes)
        (nothing == _fetch_tasks(procid, ip, hn, true)) && continue
        _debug && println("\tstarting feeder for $(procid)")
        _feeders[procid] = @async _push_to_worker(procid)
    end
end

function _fetch_tasks(proc_id::Int, ip::String, hn::String, onlypeek::Bool=false)
    v = emptypq()
    function add_to_fp(q)
        (length(q) > 0) && (v[q] = peek(q)[2])
    end

    !((proc_id == 1) && (num_remotes() > 1)) && add_to_fp(_any_tasks)
    haskey(_procid_tasks, proc_id) && add_to_fp(_procid_tasks[proc_id])
    haskey(_machine_tasks, ip) && add_to_fp(_machine_tasks[ip])
    haskey(_machine_tasks, hn) && add_to_fp(_machine_tasks[hn])

    ((v == nothing) || (0 == length(v))) && return nothing

    onlypeek && (return ((length(v) > 0) ? peek(peek(v)[1]) : nothing))

    qtask = dequeue!(dequeue!(v))
    (:wrkr_all != qtask.target) && dequeue_worker_task(qtask)
    qtask
end

function _push_to_worker(procid)
    ip, hn = map(x->x[procid], _remotes)

    while(true)
        # if no tasks, exit task
        qtask = _fetch_tasks(procid, ip, hn)
        (qtask == nothing) && return

        wtask = qtask.wtask

        # call method at worker
        _debug && println("-> $(procid) $(wtask)")
        ret = remotecall_fetch(procid, qtask.remote_method, wtask)
        _debug && println("<- $(procid) $(wtask)")

        try
            if(nothing != qtask.callback)
                _debug && println("0> $(procid) $(wtask) $(typeof(ret))")
                qtask.callback(wtask, ret)
                _debug && println("<0 $(procid) $(wtask) $(typeof(ret))")
            end
        catch ex
            _debug && println("error in callback $(ex)")
            _debug && println("returned value: $(ret)")
        end
    end
end


text:
U = [-4.103287549769938	-1.350191915095031	-0.2838412996141297	0.09324840974016409	0.19077024046466484	0.17698093545373061	0.12095805805318198	0.0510280141023409	-0.021237095074871107	-0.09116319306735657	-0.1569248474096587	-0.2178804395105871	-0.2738865712290467	-0.325014667461339	-0.37143283105668556	-0.41335565056327245	-0.4510220008537108	-0.4846844231099108	-0.5146033413444906	-0.5410433456358805	-0.5642704051648825	-0.5845495458901986	-0.6021428040702357	-0.6173073808413386	-0.6302939697547607	-0.6413452481354287	-0.6506945302927174	-0.6585645828839758	-0.6651666027831791	-0.6706993568735213	-0.6753484818373133	-0.6792859405282733	-0.6826696300639791	-0.685643135282006	-0.6883356200972178	-0.6908618481308287	-0.6933223232716466	-0.6958035400630818	-0.6983783335946488	-0.7011063182441774	-0.7040344046130472	-0.7071973842325111	-0.7106185717411012	-0.7143104947782586	-0.7182756220995562	-0.7225071211185771	-0.7269896364756209	-0.7317000818983985	-0.736608438139306	-0.7416785503296592	-0.7468689187543158	-0.7521334773677102	-0.7574223551847615	-0.7626826158694128	-0.7678589716259433	-0.7728944676370367	-0.7777311340702502	-0.7823106027762945	-0.7865746864662924	-0.7904659183975686	-0.793928051026152	-0.7969065124886033	-0.799348820052218	-0.8012049501117011	-0.8024276645615136	-0.8029727937427777	-0.8027994764401563	-0.8018703576937566	-0.8001517454720307	-0.7976137274747559	-0.7942302495773801	-0.7899791576514618	-0.7848422046234391	-0.7788050248626875	-0.7718570780790691	-0.7639915650246232	-0.7552053174157958	-0.7454986645154538	-0.7348752788821762	-0.7233420038127969	-0.7109086649669869	-0.6975878687229596	-0.683394789646778	-0.668346949535857	-0.6524639903156949	-0.6357674430241205	-0.6182804950334542	-0.6000277574817315	-0.5810350348451259	-0.5613290983596306	-0.5409374649520491	-0.5198881831081288	-0.49820962704170363	-0.47593030029480343	-0.4530786498328655	-0.42968289147492456	-0.40577084740779745	-0.38136979635603585	-0.3565063368533462	-0.33120626392504354	-0.3054944593744501	-0.2793947957152367	-0.2529300537248118	-0.22612185344648805	-0.19899059840466116	-0.17155543268897896	-0.14383421049639156	-0.11584347765857302	-0.087598464593835	-0.059113090118268284	-0.03039997545180872	-0.001470467783075028	0.027665327335713988	0.05699850544096918	0.08652131521835552	0.11622710387290858	0.14611025655308163	0.17616613055557717	0.20639098500587086	0.2367819067412114	0.267336733042984	0.2980539719022343	0.3289327204283981	0.359972582020467	0.39117358286479054	0.42253608830833483	0.45406071961045	0.48574827156105116	0.5175996314012054	0.5496156994547267	0.5817973118565182	0.6141451657098009	0.6466597469821987	0.6793412614278769	0.7121895687637801	0.7452041203269414	0.7783839003917419	0.8117273712970048	0.8452324225179494	0.8788963237790415	0.9127156822733726	0.9466864040602225	0.9808036596449057	1.015061853761471	1.0494545993342197	1.0839746955940206	1.1186141102895668	1.1533639659212886	1.1882145299343043	1.223155208743406	1.2581745455048166	1.2932602214979487	1.3283990609831622	1.363577039406735	1.3987792947820423	1.4339901421009993	1.4691930906095065	1.504370863777508	1.53950542177088	1.574577986280581	1.609569067497783	1.644458493065324	1.679225438822319	1.7138484611529572	1.7483055307686688	1.7825740677209208	1.816630977490029	1.850452687952417	1.8840151870746593	1.917294061141138	1.950264533373402	1.9829015027661703	2.015179583001643	2.0470731412752348	2.0785563369095588	2.1096031596199047	2.140187467283559	2.1702830231409482	2.1998635322474995	2.2289026771378344	2.2573741525813706	2.2852516993142347	2.3125091367241652	2.3391203943623795	2.3650595422611254	2.390300819973459	2.414818664305769	2.4385877356975394	2.461582943218487	2.483779468165808	2.5051527862352247	2.525678688269967	2.5453332995827003	2.564093097850737	2.5819349296039906	2.5988360253338736	2.6147740132063295	2.629726931483832	2.6436732396069993	2.6565918280334118	2.6684620268695	2.6792636133138727	2.6889768180005027	2.6975823302844195	2.7050613025066395	2.7113953533446176	2.7165665702584922	2.7205575111438036	2.723351205226467	2.72493115328031	2.7252813272343066	2.72438616923393	2.722230590232961	2.7187999681816803	2.714080145877072	2.708057428544721	2.7007185812391166	2.6920508260970535	2.6820418395491017	2.6706797495026935	2.657953132658955	2.64385101187713	2.6283628538374955	2.611478566874252	2.593188499206441	2.5734834374949904	2.5523546058752284	2.5297936654799416	2.5057927145196315	2.4803442889597807	2.453441363882087	2.425077355540396	2.3952461242072443	2.3639419778115816	2.3311596764517657	2.296894437815233	2.261141943550965	2.22389834662823	2.1851602797473237	2.1449248648029493	2.1031897234761505	2.0599529889414203	2.0152133187770733	1.9689699090404291	1.9212225096032751	1.8719714406793735	1.8212176106778422	1.7689625352506195	1.7152083576797712	1.659957870513392	1.6032145384732106	1.5449825226499172	1.4852667059217157	1.4240727196138598	1.3614069713310748	1.2972766739951052	1.2316898758974923	1.1646554918935659	1.0961833355266761	1.0262841520563282	0.954969652324457	0.8822525473114822	0.8081465833333928	0.7326665776830724	0.6558284546489509	0.5776492817348708	0.4981473058845687	0.41734198965849684	0.33525404699132394	0.2519054785212889	0.16731960616266392	0.08152110675051263	-0.005463955506039365	-0.09360809797835938	-0.1828823902249186	-0.2732564265693566	-0.36469830081781307	-0.4571745835038981	-0.5506503018598852	-0.6450889228197434	-0.7404523393314537	-0.8367008602770369	-0.9337932042630251	-1.0316864975282614	-1.130336276298646	-1.2296964937329562	-1.3297195318228836	-1.4303562183372802	-1.5315558491173389	-1.6332662158204532	-1.7354336393073377	-1.8380030087471408	-1.9409178265870284	-2.044120259376866	-2.147551194532152	-2.2511503028992803	-2.354856107207966	-2.4586060561937697	-2.562336604239557	-2.66598329643519	-2.7694808586748363	-2.872763292625725	-2.975763975163261	-3.0784157619541963	-3.180651094661766	-3.2824021114962227	-3.383600760417211	-3.4841789146347373	-3.5840684897095776	-3.6832015617969365	-3.7815104863565834	-3.8789280166787523	-3.975387421769007	-4.070822602706279	-4.165168207083543	-4.258359740752957	-4.3503336763591225	-4.441027557983624	-4.530380101433774	-4.618331289549727	-4.70482246211228	-4.789796399789058	-4.873197401831856	-4.954971357031404	-5.035065807707204	-5.113430006384558	-5.190014965039972	-5.264773496656919	-5.337660249102966	-5.4086317311815195	-5.477646330958506	-5.5446643263675774	-5.609647888233976	-5.672561075917426	-5.733369825715114	-5.792041932336584	-5.84854702371906	-5.902856529527176	-5.954943643643342	-6.004783281090289	-6.052352029747703	-6.0976280972803405	-6.140591253720991	-6.181222770100182	-6.219505353621435	-6.255423079734319	-6.28896132159641	-6.320106677310262	-6.34884689532199	-6.375170798439975	-6.399068206734741	-6.420529859789144	-6.439547338534466	-6.456112987048938	-6.470219834566981	-6.4818615179671975	-6.491032204989873	-6.497726518394599	-6.501939461238658	-6.503666343462604	-6.502902709926548	-6.499644270020991	-6.493886828964575	-6.4856262208853055	-6.474858243764926	-6.461578596290752	-6.445782816695129	-6.427466223593995	-6.40662385889329	-6.383250432736162	-6.357340270582812	-6.328887262379395	-6.297884813878768	-6.26432580011961	-6.228202521078872	-6.189506659566392	-6.1482292413520145	-6.104360597616423	-6.057890329769364	-6.0088072767006295	-5.9570994845807945	-5.902754179281975	-5.845757741574514	-5.786095685229549	-5.723752638190464	-5.658712327010628	-5.590957564769066	-5.520470242688617	-5.447231325750879	-5.371220852564473	-5.292417939834628	-5.2108007917732255	-5.12634671482833	-5.039032138138557	-4.9488326401687806	-4.855722981965902	-4.75967714756404	-4.660668392041384	-4.558669297796143	-4.453651839613106	-4.3455874591210035	-4.234447149279786	-4.120201549517169	-4.002821052184631	-3.882275920990322	-3.758536422092653	-3.6315729684983418	-3.5013562784604595	-3.367857548487327	-3.231048641606548	-3.090902291475999	-2.947392322860687	-2.8004938889933166	-2.6501837262107064	-2.496440426222065	-2.33924472623594	-2.178579817041197	-2.0144316690855923	-1.8467893762922087	-1.6756455173664122	-1.500996533972574	-1.3228431250464943	-1.1411906562769942	-0.9560495833975821	-0.7674358878350552	-0.5753715227584852	-0.37988486736609334	-0.18101118683650347	0.02120690499884949	0.22671898357381726	0.43546635582970544	0.6473816109261331	0.8623881839325482	1.0803999374703497	1.3013207666111846	1.5250442327288136	1.7514532323038026	1.9804197070007792	2.211804401470138	2.445456675587395	2.681214377807994	2.9189037862954703	3.158339624367799	3.399325156455402	3.6416523703760375	3.8851022511843514	4.129445151015099	4.37444125864656	4.619841171208494	4.865386569501732	5.110810996869413	5.355840740153126	5.600195809699273	5.843591013610069	6.08573711984679	6.326342097898225	6.565112430109767	6.801754481077487	7.035975911984316	7.267487125342728	7.4960027244848515	7.7212429711716215	7.942935224066474	8.16081534051001	8.374629023994775	8.584133100191126	8.789096705008278	8.989302369387012	9.184546986770401	9.374642651125347	9.55941735522121	9.738715541259028	9.912398498170651	10.080344602624287	10.242449403180341	10.398625549684557	10.548802572439133	10.692926518055623	10.83095945101768	10.962878831940902	11.088676785113293	11.208359269268806	11.321945166511489	11.429465304988636	11.530961431202341	11.626485147861025	11.71609683281071	11.799864553966694	11.877862994285998	11.950172399707117	12.016877561685307	12.078066844523805	12.133831266165176	12.184263639507078	12.22945777970943	12.269507781377309	12.304507367938225	12.334549314130292	12.35972494114419	12.380123682754034	12.39583271973061	12.406936678882461	12.413517392355635	12.415653712204843	12.413421374837377	12.406892909640382	12.396137585979224	12.381221392729437	12.362207044644585	12.339154010037042	12.31211855458511	12.281153796398502	12.246309767920291	12.207633480665379	12.165168989247984	12.118957451645866	12.06903718303899	12.015443701043555	11.958209760510096	11.897365376423995	11.832937833748069	11.764951683292415	11.693428722926408	11.618387963548361	11.539845579395488	11.457814842308155	11.372306039563364	11.283326374922769	11.190879852472062	11.094967142772544	10.995585430790019	10.892728244966666	10.786385266723459	10.676542119621272	10.563180137361845	10.446276109688812	10.3258020053217	10.201724671045225	10.07400550597844	9.942600110296736	9.807457907631589	9.668521740583813	9.525727438848476	9.379003359808387	9.228269901560052	9.073438988691235	8.914413531532169	8.751086859876617	8.583342132801928	8.411051726573314	8.234076603479895	8.05226566490939	7.865455092973095	7.673467685844155	7.476112193065783	7.273182658288517	7.064457778238113	6.849700288412783	6.628656387475522	6.401055214681095	6.166608396492031	5.925009681251739	5.6759346834168625	5.41904076187114	5.153967060032825	4.880334739231809	4.59774744035939	4.305792013195397	4.004039556722776	3.692046818507369	3.3693580053737167	3.035507062186317	2.690020479685677	2.3324206960241862	1.9622301597266407	1.5789761239021314	1.1821962420568068	0.7714450345922421	0.34630129134864657	-0.09362353176502441	-0.5486758748085283	-1.0191495638091392	-1.5052742200063136	-2.0072026095616584	-2.5249969929458986	-3.0586145810303225	-3.6078922638325635	-4.172530847369905	-4.752079115756934	-5.3459181262729185	-5.953246244975354	-6.573065531474982	-7.20417018078097	-7.845137815753748	-8.494324485270527	-9.1498642483439	-9.80967419723899	-10.47146568302403	-11.132762342489137	-11.790925285475033	-12.443185486504856	-13.086683050785963	-13.71851261178392	-14.335773699035856	-14.93562452418662	-15.515337310812866	-16.072353072451598	-16.604333649405547	-17.10920886616867	-17.585216865252168	-18.030936000505115	-18.445307105018287	-18.82764545233775	-19.177642262131428	-19.495356121755517	-19.78119516381484	-20.035891225675527	-20.260467497273712	-20.456201329158887	-20.624583921588194	-20.76727856030845	-20.886078921429807	-20.98286875955055	-21.059584045282346	-21.118178352624277	-21.160592035565404	-21.188725491879982	-21.204416602527967	-21.209422263400423	-21.205403794715203	-21.19391592078516	-21.176398955364014	-21.154173800164237	-21.128439360597977	-21.100271997251912	-21.070626659161825	-21.040339380418	-21.010130861476853	-20.980610897742967	-20.952283457984635	-20.925552252547725	-20.900726664782727	-20.8780279479124	-20.85759561335776	-20.83949395488291	-20.823718666188114	-20.810203517720293	-20.79882706172622	-20.789419334040343	-20.781768516690143	-20.775627518682935	-20.77072042375028	-20.766748744837997	-20.763397416601087	-20.760340450444904	-20.75724617272779	-20.753781966563	-20.749618441944932	-20.744432968224235	-20.737912517024956	-20.729755782714705	-20.7196745702081	-20.70739446566612	-20.692654832712616	-20.67520820371348	-20.654819160652917	-20.631262821465143	-20.60432306374096	-20.57379062740813	-20.539461240259993	-20.50113390494698	-20.4586094732545	-20.41168961400063	-20.360176255892775	-20.303871557668487	-20.242578426704753	-20.17610157593359	-20.104249079141304	-20.02683435836464	-19.943678515411584	-19.854612903568867	-19.759481825854866	-19.658145242839606	-19.550481375745907	-19.436389098647197	-19.3157900260254	-19.18863021776922	-19.054881441470943	-18.914541950598846	-18.76763675551566	-18.61421738155	-18.45436112352682	-18.288169818929706	-18.115768171727964	-17.93730166587534	-17.75293411157546	-17.56284486883045	-17.36722579187892	-17.16627793529754	-16.96020805812884	-16.749224956968423	-16.533535652762506	-16.31334144960673	-16.088833877371098	-15.860190523780611	-15.627570755836587	-15.39111132537761	-15.150921849142167	-14.907080150086529	-14.659627443628356	-14.408563350383995	-14.153840715094569	-13.89536021020225	-13.632964701476872	-13.366433352048128	-13.095475440154441	-12.81972386418702	-12.538728306603609	-12.251948025295821	-11.958744237209142	-11.65837205425438	-11.349971926368985	-11.032560540822931	-10.705021122077099	-10.36609307345778	-10.014360902781968	-9.648242382039843	-9.265975909598758	-8.865607078459233	-8.444974512110033	-8.00169512045356	-7.533149063378683	-7.036464903915405	-6.5085057035166916	-5.945857180334338	-5.344819539559793	-4.701405217091184	-4.011345575457658	-3.2701105663067445	-2.4729465235406916	-1.6149385387938853	-0.6911052075374517	0.3034652515318506	1.3734277009635698	2.5229318861332386	3.7553052339144677	5.072662649180086	6.47544701146434	7.961916518517756	9.527612892538505	11.164867070664064	12.862422995009178	14.60527821425246	16.374840873736428	18.149473604442676	19.905428275418675	21.618078210592333	23.263253453123042	24.81842382209757	26.263496304785594	27.581112202180126	28.756512585225483	29.777212919788585	30.632804982981128	31.315138816547464	31.818949322613697	32.14276377506591	32.289762949814694	32.26824342990786	32.09144800305573	31.776734745225266	31.34425274232412	30.81540925768653	30.211422386096057	29.552175962277552	28.855477316953042	28.136710329366338	27.40880464117304	26.682413391688183	25.96619735713359	25.267137800544923	24.59082986206942	23.94173397624434	23.3233807404159	22.738534714835005	22.189326556919102	21.677362935387514	21.20382178908728	20.76953804207597	20.37508261454936	20.02083578617955	19.707054707975757	19.43393402566919	19.201658044478595	19.01044252528307	18.86056399240946	18.752374335683594	18.686298523864924	18.662813457059222	18.68240642780188	18.74551238635246	18.852430252868498	19.003219900465826	19.197583127520858	19.43473388471693	19.713265117535542	20.031021676813033	20.38499063935958	20.771221821946952	21.184791980705562	21.61982585288227	22.069585509910524	22.526636184765685	22.983091654111906	23.430935425445995	23.86240569937175	24.270422986831456	24.6490303654852	24.993808978173742	25.302226993610137	25.573880259415173	25.81058826258538	26.01632001646788	26.196940391556367	26.35978645868436	26.51310305812434	26.665384097595005	26.824678254196538	26.997922811602447	27.190366493888746	27.405131892150035	27.642952141498355	27.90209740927066	28.17848728096092	28.465967810631135	28.756718732302595	29.04174816625685	29.311429309004396	29.556035564483764	29.76623635836551	29.93352422306723	30.050553353817694	30.11137954601387	30.111600292519665	30.048401190031704	29.920520309000935	29.728145715281705	29.47276300013626	29.15696973634735	28.784272580049848	28.358880661704337	27.88550632325597	27.36918148385174	26.815095210062573	26.228455612418557	25.61437710391147	24.977792391858756	24.32338734084351	23.655556013269628	22.978372717410714	22.295577709576676	21.610573242356935	20.926426862653468	20.245879184038703	19.571353739647737	18.904966925660286	18.248536442701283	17.603587015133492	16.971352506443154	16.35277385153113	15.748492497910139	15.158839295863071	14.583819012285895	14.023090873020795	13.475945769444719	12.941280996763169	12.417573616082246	11.902853732661752	11.394679131959688	10.890112775870612	10.385704588995335	9.877478708622883	9.360926881752569	8.831007925184727	8.282152089390042	7.708267774338822	7.102746349913155	6.458458871882798	5.76773630956827	5.0223225669468174	4.213287115140094	3.330881447142525	2.36432072888291	1.3014687930403572	0.1284007819705767	-1.171186912172336	-2.6167552633512163	-4.231931478211859	-6.045794249332406	-8.094480126336785	-10.423138181852144	-13.088203418692185	-16.159812808392527	-19.7238423861618	-23.88227555160669	-28.74900687486189	-34.43512318167695	-41.01269670262679	-48.44008679474715	-56.42970622109752	-64.25346711705568	-70.53023441228598	-73.13451787490457	-69.47452320706286	-57.38779348051679	-36.58938386589305	-9.929587556038761	16.766610331494054	36.80707702616308	45.49265133413475	41.800944183625894	28.274873735348585	9.712263084432191	-8.829127713947722	-23.75922696418008	-33.64977289307627	-38.89530683545099	-40.76510778117236	-40.5483607631502	-39.150675097651664	-37.04758198034058	-34.38736565181248	-31.120770897069544	-27.116849551905677	-22.257789931855942	-16.510910577432647	-9.971995269372746	-2.8703798826864104	4.468437805960417	11.676530108407906	18.373487388252265	24.195281950716147	28.842768718757757	32.12173367814701	33.95518980716499	34.36972944859329	33.46806179633954	31.399925837953237	28.33760605151969	24.45819290308709	19.933207571664965	14.925059221054909	9.588663786843352	4.075848771630728	-1.459843787881771	-6.8598063826588875	-11.959693498789186	-16.59230393888	-20.594715919699773	-23.819945678613973	-26.152365143194814	-27.52433497863209	-27.9292936718577	-27.425366504593743	-26.12589031039615	-24.179376486400947	-21.74694270325622	-18.98543950876176	-16.040245358228212	-13.047208095593257	-10.140608312046158	-7.462949822480033	-5.172267869165521	-3.4433828779559397	-2.4612340233782013	-2.4072188550743903	-3.4423352712794384	-5.690746533901264	-9.220904083811481	-14.010168518979574	-19.875725309866986	-26.379833478698664	-32.76609861307639	-38.01159019984622	-41.05349793022043	-41.156165744131364	-38.238795371628804	-32.85843129562779	-25.50261068517388	-16.414414771877716	-8.92520694229556	-8.072245146078387	-10.834896220403492	-8.793064280894965	-5.308228012805314	-11.290690986330253	-21.696339307812853	-34.440604204738115	-46.59944590785906	-45.82984413797587]

using ConstrainedDynamics
using ConstrainedControl
using LinearAlgebra
using Rotations
using Rotations: rotation_error

# Trajectory Generation from U

# Parameters
ex = [1.0;0.0;0.0]
ey = [0.0;1.0;0.0]

length1 = 1.0
width, depth = 0.1, 0.1

p2 = [0.0;0.0;length1/2] # joint connection point

# Desired orientation
ϕ = 0.

# Links
origin = Origin{Float64}()
cart = Box(0.1, 0.5, 0.1, length1/2)
pole1 = Box(width, depth, length1, length1)
pole2 = deepcopy(pole1)
pole3 = deepcopy(pole1)

# Constraints
joint1 = EqualityConstraint(Prismatic(origin, cart, ey))
joint2 = EqualityConstraint(Revolute(cart, pole1, ex; p2=p2))
joint3 = EqualityConstraint(Revolute(pole1, pole2, ex; p1 = -p2, p2=p2))
joint4 = EqualityConstraint(Revolute(pole2, pole3, ex; p1 = -p2, p2=p2))

links = [cart;pole1;pole2;pole3]
constraints = [joint1;joint2;joint3;joint4]

mech = Mechanism(origin, links, constraints, g=-9.81,Δt = 0.01)
setPosition!(origin,cart,Δx = [0;0.0;0])
setPosition!(cart,pole1,p2 = p2,Δq = UnitQuaternion(RotX(ϕ+0)))
setPosition!(pole1,pole2,p1 = -p2,p2 = p2,Δq = UnitQuaternion(RotX(0.)))
setPosition!(pole2,pole3,p1 = -p2,p2 = p2,Δq = UnitQuaternion(RotX(0.)))

function control!(mechanism, k)
    setForce!(mechanism, geteqconstraint(mechanism,5), [U[k]])
end

steps = Base.OneTo(1000)
storage0 = Storage{Float64}(steps,4)

simulate!(mech,storage0,control!,record = true);

# Tracking Control

setPosition!(origin,cart,Δx = [0;0.0;0])
setPosition!(cart,pole1,p2 = p2,Δq = UnitQuaternion(RotX(0.)))
setPosition!(pole1,pole2,p1 = -p2,p2 = p2,Δq = UnitQuaternion(RotX(0.)))
setPosition!(pole2,pole3,p1 = -p2,p2 = p2,Δq = UnitQuaternion(RotX(0.)))

Q = [diagm(ones(12))*0.0 for i=1:4]
Q[1][2,2] = 10
Q[1][5,5] = 1
Q[2][7,7] = 40
Q[2][10,10] = 1
Q[3][7,7] = 40
Q[3][10,10] = 1
Q[4][7,7] = 40
Q[4][10,10] = 1
R = [ones(1,1)*0.1]

ucost = zeros(1000)

lqr = TrackingLQR(mech, storage0, [[[U[k]]] for k=1:1000], [5], Q, R)
@test true


text:
# %%
using Random,
      Distributions,
      LinearAlgebra,
      StatsBase,
      StatsPlots,
      StatFiles

Random.seed!(123)

function sim_data(k,n, T; doplot = false)
    # true values
    μ = randn(k) * 3
    # for i in 1:k
    #     μ[i] = (μ[i]+2*i)*(-1)^i
    # end

    σ = abs.(randn(k))./2
    p = rand(k)
    p = p / sum(p)
    K_draw = sample(1:k, Weights(p), n, replace = true)
    Y = Matrix{Float64}(undef, n, T)
    for t in 1:T
        Y[:, t] = rand.(Normal.(μ[K_draw], σ[K_draw]))
    end

    return Dict(:y => Y, :μ => μ, :σ => σ, :p => p, :K_draw => K_draw)
end

# Pretty much directly inherited from Thomas Wiemann
mutable struct GaussMix
    μ # component means
    σ # component standard devs
    probs # component probabilities
    probs_post # posterior component probabilities
    y # data
    K # number of components
    function GaussMix(y, K)
        # Initialize component parameters randomly
        nobs = length(y)
        μ = rand(Normal(0, std(y)), K)
        σ = std(y) * ones(K) ./ K
        probs = rand(Dirichlet(ones(K)))
        probs_post = zeros((nobs , K))
        # Construct object
        new(μ, σ, probs, probs_post, y, K)
    end
end

# This too
function par_fit!(m:: GaussMix; max_iter = 1000, tol = 1e-2)
    # Get values from m
    μ = m.μ; σ = m.σ
    probs = m.probs; probs_post = m.probs_post
    K = m.K; nobs = length(m.y)

    # Run EM algorithm
    likeli = zeros((nobs , K))
    log_l = zeros(max_iter)
    for j in 1:max_iter
        # E-step
        for k in 1:K
            likeli[:, k] = pdf.(Normal(μ[k], σ[k]), m.y) .* probs[k]
        end
        probs_post = likeli ./ repeat(mapslices(sum , likeli , dims = 2)', K)'

        # M-step
        for k in 1:K
            sum_prob_post = sum(probs_post[:, k])
            probs[k] = mean(probs_post[:, k])
            μ[k] = sum(m.y .* probs_post[:, k]) ./ sum_prob_post
            σ[k] = sum((m.y .- μ[k]).^2 .* probs_post[:, k]) ./ sum_prob_post
            σ[k] = sqrt(σ[k])
        end
        # Compute current value of the likelihood
        mixture_j = MixtureModel(Normal , [(μ[k], σ[k]) for k in 1:K], probs)
        log_l[j] = sum(logpdf.(mixture_j, m.y))

    end
    # Export values to m
    m.μ = μ; m.σ = σ
    m.probs = probs; m.probs_post = probs_post
    return nothing
end

# EM funcs

nk_test = 3
n_test = 2000

fake_sim_data = sim_data(nk_test, n_test, 3)
Y_test = fake_sim_data[:y]
Y1_test = Y_test[:, 1]
Y2_test = Y_test[:, 2]
Y3_test = Y_test[:, 3]

mix_model_test = GaussMix(Y1_test[:], nk_test)
par_fit!(mix_model_test)

hcat(sort(mix_model_test.μ), sort(fake_sim_data[:μ]))

using Plots
p_data = density(Y1_test);
p_estimated = plot(Normal.(mix_model_test.μ, mix_model_test.σ));
p_true = plot(Normal.(fake_sim_data[:μ], fake_sim_data[:σ]));
l = @layout [a ; b ; c]
plot(
    p_data,
    p_estimated,
    p_true,
    layout = l
)

using DataFrames, GLM
stat_df = DataFrame(load("data/AER_2012_1549_data/output/data4estimation.dta"))

stat_df

fit = lm(
    @formula(log_y ~ year + marit + state_st),
    stat_df
)

using Pkg
Pkg.add(url="https://github.com/EdJeeOnGitHub/Jeeves")

regression_df = select(
    stat_df,
    ["log_y",
     "year",
     "person",
     "marit",
     "state_st"]
)
using Jeeves
clean_regression_df = regression_df[completecases(regression_df), :]

year_dummy_matrix = Jeeves.dummy_matrix(clean_regression_df, "year")
state_dummy_matrix = Jeeves.dummy_matrix(clean_regression_df, "state_st")

model = Jeeves.OLSModel(
    clean_regression_df.log_y,
    hcat(
        clean_regression_df[!, ["marit"]],
        year_dummy_matrix[!, 2:end],
        state_dummy_matrix
    )
)

year_dummy_matrix[!, 2:end]

jeeves_fit = Jeeves.fit(model)
fit_resid = jeeves_fit.modelfit.resid
Jeeves.tidy(jeeves_fit)

clean_regression_df[!, "y_resid"] = fit_resid
clean_regression_df
using Chain, DataFramesMeta
psid_y_data = @chain clean_regression_df begin
    sort([:person, :year])
    groupby([:person])
    @transform(
        :y_resid_lead_1 = lead(:y_resid),
        :y_resid_lead_2 = lead(:y_resid, 2),
        :y_resid_lead_3 = lead(:y_resid, 3)
    )
    @select(:y_resid, :y_resid_lead_1, :y_resid_lead_2, :y_resid_lead_3)
end

psid_y_data = psid_y_data[completecases(psid_y_data[!, [:y_resid,
                                                        :y_resid_lead_1,
                                                        :y_resid_lead_2]]), :]

psid_mix_models_3 = GaussMix.([psid_y_data.y_resid,
                               psid_y_data.y_resid_lead_1,
                               psid_y_data.y_resid_lead_2], 3)
psid_mix_models_4 = GaussMix.([psid_y_data.y_resid,
                               psid_y_data.y_resid_lead_1,
                               psid_y_data.y_resid_lead_2], 4)
psid_mix_models_5 = GaussMix.([psid_y_data.y_resid,
                               psid_y_data.y_resid_lead_1,
                               psid_y_data.y_resid_lead_2], 5)
par_fit!.(vcat(psid_mix_models_3, psid_mix_models_4, psid_mix_models_5))

psid_models = vcat(
    psid_mix_models_3,
    psid_mix_models_4,
    psid_mix_models_5
)
using StatsPlots

function plot_mixture(mix_model)
    mm_model = MixtureModel(
            Normal.(
                mix_model.μ,
                mix_model.σ
            ),
            mix_model.probs
        )
    p_estim = plot(
        mm_model
    )
    p_data = density(mix_model.y, label = "Y Observed")
    p_stacked_dens = plot(x -> pdf(mm_model, x), minimum(mix_model.y), maximum(mix_model.y),
                            label = "Y Estim" )
    p_all = plot(
        p_data,
        p_stacked_dens,
        p_estim,
        layout = @layout [a ; b ; c])
    return p_all
end

plot_mixture(psid_mix_models_3[1])
plot_mixture(psid_mix_models_4[1])
plot_mixture(psid_mix_models_5[1])

plot_mixture(psid_mix_models_3[2])
plot_mixture(psid_mix_models_4[2])
plot_mixture(psid_mix_models_5[2])

plot_mixture(psid_mix_models_3[3])
plot_mixture(psid_mix_models_4[3])
plot_mixture(psid_mix_models_5[3])

function gen_mm_model(m::GaussMix)

    mm_model = MixtureModel(
            Normal.(
                m.μ,
                m.σ
            ),
            m.probs
        )
    return mm_model
end

mm_models = gen_mm_model.(
    vcat(psid_mix_models_3,
         psid_mix_models_4,
         psid_mix_models_5)
)

test_mm = mm_models[1]
quantile(psid_mix_models_3[1].y, 0.0:0.01:1.0)

quantile(test_mm, 0.0:0.01:1.0)

function qq_mixtures(estim_m::GaussMix)
    mix_model = gen_mm_model(estim_m)

    q_data = quantile(estim_m.y, 0.0:0.01:1.0)
    q_pdf = quantile(mix_model, 0.0:0.01:1.0)
    df = DataFrame(
        :q_data => q_data,
        :q_pdf => q_pdf
    )
    return df
end

qq_dfs = qq_mixtures.(psid_models)

function plot_qq(qq_mix)

    plot(qq_mix.q_data, qq_mix.q_pdf, seriestype = :scatter,
         xlabel = "Data", ylabel = "Mixture PDF", label = "QQ")
    Plots.abline!(1, 0, label = "Theoretical")
    Plots.xlims!(minimum(qq_mix.q_data[2:end]), maximum(qq_mix.q_data[1:(end-1)]))
end

plot(
    plot_qq(qq_dfs[1]),
    plot_qq(qq_dfs[2]),
    plot_qq(qq_dfs[3]),
    plot_qq(qq_dfs[4])
    )

fd_df = function (df, ρ)

    new_df = @chain df begin
        @transform(
            :y_fd_3 = :y_resid_lead_3 - ρ*:y_resid_lead_2,
            :y_fd_2 = :y_resid_lead_2 - ρ*:y_resid_lead_1,
            :y_fd_1 = :y_resid_lead_1 - ρ*:y_resid
        )
    end
    new_df = new_df[completecases(new_df), :]
    return new_df
end

fd_psid_df = fd_df(psid_y_data, 0.6)

fd_mix_models_3 = GaussMix(fd_psid_df.y_fd_1, 3)
fd_mix_models_4 = GaussMix(fd_psid_df.y_fd_1, 4)
fd_mix_models_5 = GaussMix(fd_psid_df.y_fd_1, 5)

fd_mix_models = vcat(
    fd_mix_models_3,
    fd_mix_models_4,
    fd_mix_models_5
)

par_fit!.(fd_mix_models)

plot_mixture(fd_mix_models[1])
plot_mixture(fd_mix_models[2])
plot_mixture(fd_mix_models[3])

qq_fd_dfs = qq_mixtures.(fd_mix_models)

plot(
    plot_qq(qq_fd_dfs[1]),
    plot_qq(qq_fd_dfs[2]),
    plot_qq(qq_fd_dfs[3])
)

# We didn't do MLE sorry


text:
# ---
# title: 117. Populating Next Right Pointers in Each Node II
# id: problem117
# author: Tian Jun
# date: 2020-10-31
# difficulty: Medium
# categories: Tree, Depth-first Search
# link: <https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/description/>
# hidden: true
# ---
#
# Given a binary tree
#
#
#
#     struct Node {
#       int val;
#       Node *left;
#       Node *right;
#       Node *next;
#     }
#
#
# Populate each next pointer to point to its next right node. If there is no
# next right node, the next pointer should be set to `NULL`.
#
# Initially, all next pointers are set to `NULL`.
#
#
#
# **Follow up:**
#
#   * You may only use constant extra space.
#   * Recursive approach is fine, you may assume implicit stack space does not count as extra space for this problem.
#
#
#
# **Example 1:**
#
# ![](https://assets.leetcode.com/uploads/2019/02/15/117_sample.png)
#
#
#
#     Input: root = [1,2,3,4,5,null,7]
#     Output: [1,#,2,3,#,4,5,7,#]
#     Explanation: Given the above binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B. The serialized output is in level order as connected by the next pointers, with '#' signifying the end of each level.
#
#
#
#
# **Constraints:**
#
#   * The number of nodes in the given tree is less than `6000`.
#   * `-100 <= node.val <= 100`
#
#
## @lc code=start
using LeetCode

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


text:
function softmax!(x::A) where A<:AbstractVecOrMat
    x = Float32.(x)
    softmax!(x)
end

softmax!(y::A, x::B) where {A<:AbstractVecOrMat, B<:AbstractVecOrMat} = softmax!(Float32.(y), Float32.(x))

softmax(x::A) where A<:AbstractVecOrMat = softmax(Float32.(x))

maxpool(x::A, k; pad = map(_->0,k), stride = k) where A<:AbstractArray{T, 4} where T =
    maxpool(Float32.(x), k, pad = pad, stride = stride)

maxpool!(y::A, x::B, k; pad = map(_->0,k), stride = k) where {A<:AbstractArray{T, 4} where T, B<:AbstractArray{T, 4} where T} =
    maxpool!(Float32.(y), Float32.(x), k, pad = pad, stride = stride)

conv(x::A, w::B; pad = 0, stride = 1, dilation = 1, algo = UInt32(0)) where {A<:AbstractArray{T, 4} where T, B<:AbstractArray{T, 4} where T} =
    conv(Float32.(x), Float32.(w), pad = pad, stride = stride, dilation = dilation, algo = algo)

conv(x::A, w::B, b::C; pad = 0, stride = 1, dilation = 1, algo = UInt32(0)) where {A<:AbstractArray{T, 4} where T, B<:AbstractArray{T, 4} where T, C<:AbstractArray{T, 1} where T} =
    conv(Float32.(x), Float32.(w), Float32.(b), pad = pad, stride = stride, dilation = dilation, algo = algo)

conv!(y::A, x::B, w::C, b::D; pad = 0, stride = 1, dilation = 1, algo = UInt32(0), flipkernel = 0) where {A<:AbstractArray{T, 4} where T, B<:AbstractArray{T, 4} where T, C<:AbstractArray{T, 4} where T, D<:AbstractArray{T, 1} where T} =
    conv!(Float32.(y), Float32.(x), Float32.(w), Float32.(b), pad = pad, stride = stride, dilation = dilation, algo = algo, flipkernel = flipkernel)

∇conv_data(dy::A, x::B, w::C; pad = 0, stride = 1, dilation = 1, algo = UInt32(0)) where {A<:AbstractArray{T, 4} where T, B<:AbstractArray{T, 4} where T, C<:AbstractArray{T, 4} where T} =
    ∇conv_data(Float32.(dy), Float32.(x), Float32.(w), pad = pad, stride = stride, dilation = dilation, algo = algo)

∇conv_data!(dx::A, dy::B, x::C, w::D; pad = 0, stride = 1, dilation = 1, algo = UInt32(0), flipkernel = 0) where {A<:AbstractArray{T, 4} where T, B<:AbstractArray{T, 4} where T, C<:AbstractArray{T, 4} where T, D<:AbstractArray{T, 4} where T} =
    ∇conv_data!(Float32.(dx), Float32.(dy), Float32.(x), Float32.(w), pad = pad, stride = stride, dilation = dilation, algo = algo, flipkernel = flipkernel)

∇conv_filter(dy::A, x::B, w::C; pad = 0, stride = 1, dilation = 1, algo = UInt32(0)) where {A<:AbstractArray{T, 4} where T, B<:AbstractArray{T, 4} where T, C<:AbstractArray{T, 4} where T} =
    ∇conv_filter(Float32.(dy), Float32.(x), Float32.(w), pad = pad, stride = stride, dilation = dilation, algo = algo)

∇conv_filter!(dw::A, dy::B, x::C, w::D; pad = 0, stride = 1, dilation = 1, algo = UInt32(0), flipkernel = 0) where {A<:AbstractArray{T, 4} where T, B<:AbstractArray{T, 4} where T, C<:AbstractArray{T, 4} where T, D<:AbstractArray{T, 1} where T} =
    ∇conv_filter!(Float32.(dw), Float32.(dy), Float32.(x), Float32.(w), pad = pad, stride = stride, dilation = dilation, algo = algo, flipkernel = flipkernel)


text:
@doc raw"""
    Otsu <: AbstractImageBinarizationAlgorithm
    Otsu()

    binarize([T,] img, f::Otsu)
    binarize!([out,] img, f::Otsu)

Under the assumption that the image histogram is bimodal the binarization
threshold is set so that the resultant between-class variance is maximal.

# Output

Return the binarized image as an `Array{Gray{T}}` of size `size(img)`. If
`T` is not specified, it is inferred from `out` and `img`.

# Details

Let ``f_i`` ``(i=1 \ldots I)`` denote the number of observations in the
``i``th bin of the image histogram. Then the probability that an observation
belongs to the ``i``th bin is given by  ``p_i = \frac{f_i}{N}`` (``i = 1,
\ldots, I``), where ``N = \sum_{i=1}^{I}f_i``.

The choice of a threshold ``T`` partitions the data into two categories, ``C_0``
and ``C_1``. Let
```math
P_0(T) = \sum_{i = 1}^T p_i \quad \text{and} \quad P_1(T) = \sum_{i = T+1}^I p_i
```
denote the cumulative probabilities,
```math
\mu_0(T) = \sum_{i = 1}^T i \frac{p_i}{P_0(T)} \quad \text{and} \quad \mu_1(T) = \sum_{i = T+1}^I i \frac{p_i}{P_1(T)}
```
denote the means, and
```math
\sigma_0^2(T) = \sum_{i = 1}^T (i-\mu_0(T))^2 \frac{p_i}{P_0(T)} \quad \text{and} \quad \sigma_1^2(T) = \sum_{i = T+1}^I (i-\mu_1(T))^2 \frac{p_i}{P_1(T)}
```
denote the variances of categories ``C_0`` and ``C_1``, respectively.
Furthermore, let
```math
\mu = P_0(T)\mu_0(T) + P_1(T)\mu_1(T),
```
represent the overall mean,
```math
\sigma_b^2(T) = P_0(T)(\mu_0(T) - \mu)^2 + P_1(T)(\mu_1(T) - \mu)^2,
```
the between-category variance, and
```math
\sigma_w^2(T) = P_0(T) \sigma_0^2(T) +  P_1(T)\sigma_1^2(T)
```
the within-category variance, respectively.

Finding the discrete value ``T`` which maximises the function ``\sigma_b^2(T)``
produces the sought-after threshold value (i.e. the bin which determines the
threshold). As it turns out, that threshold value is equal to the threshold
decided by minimizing the within-category variances criterion ``\sigma_w^2(T)``.
Furthermore, that threshold is also the same as the threshold calculated by
maximizing the ratio of between-category variance to within-category variance.

# Arguments

The function argument is described in more detail below.

##  `img::AbstractArray`

The image that needs to be binarized.  The image is automatically converted
to `Gray` in order to construct the requisite graylevel histogram.

# Example

Binarize the "cameraman" image in the `TestImages` package.

```julia
using TestImages, ImageBinarization

img = testimage("cameraman")
img_binary = binarize(img, Otsu())
```

# Reference

1. Nobuyuki Otsu (1979). “A threshold selection method from gray-level histograms”. *IEEE Trans. Sys., Man., Cyber.* 9 (1): 62–66. [doi:10.1109/TSMC.1979.4310076](http://dx.doi.org/doi:10.1109/TSMC.1979.4310076)
"""
struct Otsu <: AbstractImageBinarizationAlgorithm end

function (f::Otsu)(out::GenericGrayImage, img::GenericGrayImage)
    edges, counts = build_histogram(img,  256)
    t = find_threshold(HistogramThresholding.Otsu(), counts[1:end], edges)
    @simd for i in CartesianIndices(img)
        out[i] = img[i] < t ? 0 : 1
    end
    out
end

(f::Otsu)(out::GenericGrayImage, img::AbstractArray{<:Color3}) =
    f(out, of_eltype(Gray, img))


text:
######################
### Mutable states ###
######################

mutable struct DAState{T<:AbstractFloat}
    m     :: Int
    ϵ     :: T
    μ     :: T
    x_bar :: T
    H_bar :: T
end

function DAState(ϵ::AbstractFloat)
    μ = computeμ(ϵ)
    return DAState(0, ϵ, μ, 0.0, 0.0)
end

function computeμ(ϵ::AbstractFloat)
    return log(10 * ϵ) # see NUTS paper sec 3.2.1
end

function reset!(dastate::DAState{T}) where {T<:AbstractFloat}
    dastate.μ = computeμ(dastate.ϵ)
    dastate.m = 0
    dastate.x_bar = zero(T)
    dastate.H_bar = zero(T)
end

mutable struct MSSState{T<:AbstractFloat}
    ϵ :: T
end

################
### Adaptors ###
################

abstract type StepSizeAdaptor <: AbstractAdaptor end

struct FixedStepSize{T<:AbstractFloat} <: StepSizeAdaptor
    ϵ :: T
end

function getϵ(fss::FixedStepSize)
    return fss.ϵ
end

"""
An implementation of the Nesterov dual averaging algorithm to tune step size.

References

Hoffman, M. D., & Gelman, A. (2014). The No-U-Turn Sampler: adaptively setting path lengths in Hamiltonian Monte Carlo. Journal of Machine Learning Research, 15(1), 1593-1623.
Nesterov, Y. (2009). Primal-dual subgradient methods for convex problems. Mathematical programming, 120(1), 221-259.
"""
struct NesterovDualAveraging{T<:AbstractFloat} <: StepSizeAdaptor
  γ     :: T
  t_0   :: T
  κ     :: T
  δ     :: T
  state :: DAState{T}
end

reset!(da::NesterovDualAveraging) = reset!(da.state)

function NesterovDualAveraging(γ::AbstractFloat, t_0::AbstractFloat, κ::AbstractFloat, δ::AbstractFloat, ϵ::AbstractFloat)
    return NesterovDualAveraging(γ, t_0, κ, δ, DAState(ϵ))
end

function NesterovDualAveraging(δ::AbstractFloat, ϵ::AbstractFloat)
    return NesterovDualAveraging(0.05, 10.0, 0.75, δ, ϵ)
end

function getϵ(da::NesterovDualAveraging)
    return da.state.ϵ
end

struct ManualSSAdaptor{T<:AbstractFloat} <:StepSizeAdaptor
    state :: MSSState{T}
end

function getϵ(mssa::ManualSSAdaptor)
    return mssa.state.ϵ
end

# Ref: https://github.com/stan-dev/stan/blob/develop/src/stan/mcmc/stepsize_adaptation.hpp
# TODO: merge this function with adapt!
function adapt_stepsize!(da::NesterovDualAveraging, α::AbstractFloat)
    DEBUG && @debug "Adapting step size..." α
    da.state.m += 1
    m = da.state.m

    # Clip average MH acceptance probability
    α = α > 1 ? 1 : α

    γ = da.γ; t_0 = da.t_0; κ = da.κ; δ = da.δ
    μ = da.state.μ; x_bar = da.state.x_bar; H_bar = da.state.H_bar

    η_H = 1.0 / (m + t_0)
    H_bar = (1.0 - η_H) * H_bar + η_H * (δ - α)

    x = μ - H_bar * sqrt(m) / γ     # x ≡ logϵ
    η_x = m^(-κ)
    x_bar = (1.0 - η_x) * x_bar + η_x * x

    ϵ = exp(x)
    DEBUG && @debug "Adapting step size..." "new ϵ = $ϵ" "old ϵ = $(da.state.ϵ)"

    # TODO: we might want to remove this when all other numerical issues are correctly handelled
    if isnan(ϵ) || isinf(ϵ)
        @warn "Incorrect ϵ = $ϵ; ϵ_previous = $(da.state.ϵ) is used instead."
        ϵ = da.state.ϵ
        x_bar = da.state.x_bar
        H_bar = da.state.H_bar
    end

    da.state.ϵ = ϵ
    da.state.x_bar = x_bar
    da.state.H_bar = H_bar
end

function adapt!(da::NesterovDualAveraging, θ::AbstractVector{<:AbstractFloat}, α::AbstractFloat)
    adapt_stepsize!(da, α)
end

function finalize!(da::NesterovDualAveraging)
    da.state.ϵ = exp(da.state.x_bar)
end


text:
# Hessian Eigenmaps (HLLE)
# ---------------------------
# Hessian eigenmaps: Locally linear embedding techniques for high-dimensional data,
# D. Donoho and C. Grimes, Proc Natl Acad Sci U S A. 2003 May 13; 100(10): 5591–5596

import Combinatorics: combinations

#### HLLE type
struct HLLE{T <: AbstractFloat} <: SpectralResult
    k::Int
    λ::AbstractVector{T}
    proj::Projection{T}

    HLLE{T}(k::Int, λ::AbstractVector{T}, proj::Projection{T}) where T = new(k, λ, proj)
end

## properties
outdim(M::HLLE) = size(M.proj, 1)
projection(M::HLLE) = M.proj

eigvals(M::HLLE) = M.λ
neighbors(M::HLLE) = M.k

## show & dump
function show(io::IO, M::HLLE)
    print(io, "Hessian Eigenmaps(outdim = $(outdim(M)), neighbors = $(neighbors(M)))")
end

function dump(io::IO, M::HLLE)
    show(io, M)
    println(io, "eigenvalues: ")
    Base.showarray(io, transpose(M.λ), header=false, repr=false)
    println(io)
    println(io, "projection:")
    Base.showarray(io, M.proj, header=false, repr=false)
end

## interface functions
function transform(::Type{HLLE}, X::DenseMatrix{T}; d::Int=2, k::Int=12) where T<:AbstractFloat
    n = size(X, 2)

    # Identify neighbors
    D, I = find_nn(X, k)

    # Obtain tangent coordinates and develop Hessian estimator
    hs = round(Int, d*(d+1)/2)
    W = spzeros(hs*n,n)
    for i=1:n
        # re-center points in neighborhood
        μ = mean(X[:,I[:,i]], dims=2)
        N = X[:,I[:,i]] .- μ
        # calculate tangent coordinates
        #tc = svd(transpose(N)).U[:,1:d]
        tc = svd(N).V[:,1:d]

        # Develop Hessian estimator
        Yi = [ones(k) tc zeros(k,hs)]
        for ii=1:d
            Yi[:,d+ii+1] = tc[:,ii].^2
        end
        yi = 2(1+d)
        for (ii,jj) in combinations(1:d,2)
            Yi[:, yi] = tc[:, ii] .* tc[:, jj]
            yi += 1
        end
        F = qr(Yi)
        H = transpose(Matrix(F.Q)[:,d+2:end])
        W[(i-1)*hs .+ (1:hs),I[:,i]] = H
    end

    # decomposition
    λ, V = decompose(transpose(W)*W, d)
    return HLLE{T}(k, λ, transpose(V) .* sqrt(n))
end


text:
using BISC195Labs
using Combinatorics
using Test

@testset "Lab03" begin
    bases = collect("ATGC")

    # Test match score
    for base in bases
        @test nwscore(base, base) == 1
        @test nwscore(base, base; match = 2) == 2
    end

    # Test mismatch score
    for (b1, b2) in combinations(bases, 2)
        @test nwscore(b1, b2) == -1
        @test nwscore(b1, b2; mismatch = -2) == -2
    end

    # Test gap score
    for (base) in bases
        @test nwscore(base, nothing) == -1
        @test nwscore(nothing, base) == -1
        @test nwscore(base, nothing; gap = -2) == -2
        @test nwscore(nothing, base; gap = -2) == -2
    end

end


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

using Markdown
using InteractiveUtils

# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error).
macro bind(def, element)
    quote
        local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end
        local el = $(esc(element))
        global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el)
        el
    end
end

# ╔═╡ 922d0781-b72d-45b2-95fa-4abc0b8053e2
begin
	using Plots,PlutoUI

end

# ╔═╡ 976273ce-8a30-11ec-05af-3948a202815a
md"# make a cubic"

# ╔═╡ 046adce5-d2bf-4526-9851-fdd36c0c0732
md"## 1.fisrt  let us plot a square!"

# ╔═╡ d93a970e-9d5d-473f-bc0e-cdac3615a329
let

	x=[0,10,10,10,0,0,0]
	yp(m)=[m,m,m,m,m,m,m]  #所有点的y轴坐标
	z=[0,0,10,20,20,10,0]
	scatter(x,yp(0),z, color = :bluesreds)
	plot!(x,yp(0),z)

end

# ╔═╡ 98537cfa-ed83-4faf-ac35-0373fcf8f511
md"## 2.second  step let us plot behind  square!
   cause  two square's y coordriant is difference
   so is make  new array of y coord!
"

# ╔═╡ d84e6ea2-50f6-4cad-913a-9cb2ebd5b68f
let
 md"""
  yp(m)=[m,m,m,m,m,m,m]
  eg.  yp(0)  we  get [0,0,0,0,0,0]
       yp(2)  we  get [2,2,2,2,2,2]
   you can see we get a array  with 6 elements and value is m
   how  make a function to get a different length arr with same value?
 """

	x=[0,10,10,10,0,0,0]
	yp(m)=[m,m,m,m,m,m,m]  #所有点的y轴坐标
	z=[0,0,10,20,20,10,0]

	  scatter(x,yp(0),z,)
	  plot!(x,yp(0),z)
	  scatter!(x,yp(10),z)
	  plot!(x,yp(10),z)

end

# ╔═╡ db5eb9af-d4ec-4873-aea6-d66bc14ee01c
md"## 3.lets plot upper square and bottom square"

# ╔═╡ 07becb5e-b5d0-4033-97fc-d2037dc171cd
let
	unit=20    #公用变量, 这里定义为沿着y轴的景深,或者正方形的厚度
	#make two square front-behind
	x=[0,10,10,10,0,0,0]
	yp(m)=[m,m,m,m,m,m,m]  #所有点的y轴坐标
	z=[0,0,10,20,20,10,0]
	  scatter(x,yp(0),z)
	  plot!(x,yp(0),z)
	  scatter!(x,yp(unit),z)
	  plot!(x,yp(unit),z)
	# make  upper square
	  upper_x=[0,10,10,0,0]
	  upper_y=[0,0,20,20,0]
	  upper_z=[20,20,20,20,20]
	  plot!(upper_x,upper_y,upper_z)
	#make  bottom square
	 bottom_x=[0,10,10,0,0]
	 bottom_y= [0,0,20,20,0]
	 bottom_z= [0,0,0,0,0]
	 plot!(bottom_x,bottom_y,bottom_z)
	# you find upper and bottom square has same _x and _y , _z si difference
	# so wo can make it better!
end

# ╔═╡ 265c5bfa-78c9-42a7-a4da-4ff39806411f
let
	origin1= [0,0,0]
	origin2=[0,0,10]

	#origin3=[5,5,5]
	size= [10,10,0]

	# define a function accept origin and size
	# return a array with x,y,z series
	# so  we can use series to plot a square,or more so
	function rectangle_from_coords(origin,size)
		x,y,z=origin
		w,h,l=size
		 [
			 [x,x+w,x+w,x,x],
			 [y,y,y,y,y],
			 [z,z,z+h,z+h,z]
		 ]
	 end
	rect1=rectangle_from_coords(origin1,size)
	rect2=rectangle_from_coords(origin2,size)
	#rect3=rectangle_from_coords(origin3,size)
    plot!(rect1[:1],rect1[:2],rect1[:3],label = "rect1")
	plot!(rect2[:1],rect2[:2],rect2[:3],label = "rect2")

end

# ╔═╡ 25a26791-5cc3-4d3c-8ed5-ca67010845d4
# let
#   range=-10:.5:10
#   md"""
# 	size  $(@bind size Slider(5:1:25; default=10, show_value=true))
# 	margin $(@bind margin Slider(range; default=0.0, show_value=true))
#    """
# end

# ╔═╡ 32536470-8295-4c4b-aded-fa6520cf38b1
@bind size_out Slider(5:1:25; default=10, show_value=true)

# ╔═╡ a20a046f-81a8-4453-aa56-554d929dc9d3
@bind margin_out Slider(-10:.5:10; default=0.0, show_value=true)

# ╔═╡ be929620-1161-494e-87bb-4eaad224f2d4
md"## 4. we find coords has some common so wo  make better"

# ╔═╡ 62826f0a-a342-4037-a95c-a05ae4e9e67f
let
	size=10
	margin=2
	origin1= [0,0,0]
	origin2=[0,0,size+margin]
	origin3=[size+margin,0,0]
	origin4=[size+margin,0,size+margin]

	#origin3=[5,5,5]
	size= [10,10,10]
	function rectangle_from_coords(origin,size)
		x,y,z=origin
		w,h,l=size
		 [
			 [x,x+w,x+w,x,x],
			 [y,y,y,y,y],
			 [z,z,z+h,z+h,z]
		 ]
	 end
	rect1=rectangle_from_coords(origin1,size)
	rect2=rectangle_from_coords(origin2,size)
	rect3=rectangle_from_coords(origin3,size)
	rect4=rectangle_from_coords(origin4,size)
    p1=plot!(rect1[:1],rect1[:2],rect1[:3],label = "rect1")
	p2=plot!(rect2[:1],rect2[:2],rect2[:3],label = "rect2")
	p3=plot!(rect3[:1],rect3[:2],rect3[:3],label = "rect3")
	p4=plot!(rect4[:1],rect4[:2],rect4[:3],label = "rect4")
	#plot!(rect3[:1],rect3[:2],rect3[:3],label = "rect3")
	#plot!(p1,p2,p3,p4,layout =4, legend = false)
end

# ╔═╡ 7925a6aa-9d6c-41a9-8c1d-30104662fbf1
md"## 5. seperate functional blocks
    there two parts to make a plots
  1. form  plots series
  2. use data to plots
    so  we  get two function
"

# ╔═╡ ffa5ab5c-42c4-49e3-af49-7d88c7a27cd0
function rectangle_from_data(origin,size)
		x,y,z=origin
		w,h,l=size
		 [
			 [x,x+w,x+w,x,x],
			 [y,y,y,y,y],
			 [z,z,z+h,z+h,z]
		 ]
	 end

# ╔═╡ 8bc05241-9b03-442d-bf3d-8a7dd55af452
begin

	function Rect(title::String="Rect",origin=[0,0,0],size=[10,10,10])

	  rect=rectangle_from_data(origin,size)
	  plot!(rect[:1],rect[:2],rect[:3],label = `$(title)`)
	end

end

# ╔═╡ d469fbd8-4987-42e0-bf93-188038244b2f
begin
	p1=Rect("rect1")
	p2=Rect("rect2",[10,0,0])
	p3=Rect("rect3", [0,0,10])
    p4=Rect("rect4", [10,0,10])
end

# ╔═╡ a93a4239-c53f-465b-8914-3da530a610fc
begin
	#x=[10,0,0,10,10,0]
	#y=[0,0,0,0,0,0,0]
	#z=[0,0,10,10,20,20]
end

# ╔═╡ Cell order:
# ╟─976273ce-8a30-11ec-05af-3948a202815a
# ╠═922d0781-b72d-45b2-95fa-4abc0b8053e2
# ╠═046adce5-d2bf-4526-9851-fdd36c0c0732
# ╠═d93a970e-9d5d-473f-bc0e-cdac3615a329
# ╟─98537cfa-ed83-4faf-ac35-0373fcf8f511
# ╠═d84e6ea2-50f6-4cad-913a-9cb2ebd5b68f
# ╟─db5eb9af-d4ec-4873-aea6-d66bc14ee01c
# ╠═07becb5e-b5d0-4033-97fc-d2037dc171cd
# ╠═265c5bfa-78c9-42a7-a4da-4ff39806411f
# ╟─25a26791-5cc3-4d3c-8ed5-ca67010845d4
# ╠═32536470-8295-4c4b-aded-fa6520cf38b1
# ╠═a20a046f-81a8-4453-aa56-554d929dc9d3
# ╠═be929620-1161-494e-87bb-4eaad224f2d4
# ╠═62826f0a-a342-4037-a95c-a05ae4e9e67f
# ╠═d469fbd8-4987-42e0-bf93-188038244b2f
# ╠═7925a6aa-9d6c-41a9-8c1d-30104662fbf1
# ╠═8bc05241-9b03-442d-bf3d-8a7dd55af452
# ╠═ffa5ab5c-42c4-49e3-af49-7d88c7a27cd0
# ╟─a93a4239-c53f-465b-8914-3da530a610fc

max_stars_repo_name: phpsmarter/plutonote

max_issues_repo_name: phpsmarter/plutonote

max_forks_repo_name: phpsmarter/plutonote