text:
const CuDense{ElT,VecT}                 = Dense{ElT,VecT} where {VecT<:CuVector}
const CuDenseTensor{ElT,N,StoreT,IndsT} = Tensor{ElT,N,StoreT,IndsT} where {StoreT<:CuDense}

Dense{T, SA}(x::Dense{T, SB}) where {T<:Number, SA<:CuArray, SB<:Array} = Dense{T, SA}(CuArray(x))
Dense{T, SA}(x::Dense{T, SB}) where {T<:Number, SA<:Array, SB<:CuArray} = Dense{T, SA}(collect(x.data))
Dense{T, S}(size::Integer) where {T, S<:CuArray{<:T}} = Dense{T, S}(CuArrays.zeros(T, size))
function Dense{T, S}(x::T, size::Integer) where {T, S<:CuArray{<:T}}
    arr = CuArray{T}(undef, size)
    fill!(arr, x)
    Dense{T, S}(arr)
end
Base.collect(x::CuDense{T}) where {T<:Number} = Dense(collect(x.data))
Base.complex(::Type{Dense{ElT, VT}}) where {ElT, VT<:CuArray} = Dense{complex(ElT),CuVector{complex(ElT), Nothing}}

CuArrays.CuArray(x::CuDense{ElT}) where {ElT} = CuVector{ElT}(data(x))
CuArrays.CuArray{ElT, N}(x::CuDenseTensor{ElT, N}) where {ElT, N} = CuArray{ElT, N}(reshape(data(store(x)), dims(inds(x))))
CuArrays.CuArray(x::CuDenseTensor{ElT, N}) where {ElT, N} = CuArray{ElT, N}(x)

*(D::Dense{T, AT},x::S) where {T,AT<:CuArray,S<:Number} = Dense(x .* data(D))

Base.:(==)(::Type{<:CuDense{ElT1,CVec1}}, ::Type{<:CuDense{ElT2,CVec2}}) where {ElT1,ElT2,CVec1,CVec2} = (ElT1 == ElT2)
Base.getindex(D::CuDense{<:Number})       = collect(data(D))[]
Base.getindex(D::CuDenseTensor{<:Number, 0}) = store(D)[]
LinearAlgebra.norm(T::CuDenseTensor) = norm(data(store(T)))

# This is for type promotion for Scalar*Dense
function Base.promote_rule(::Type{<:Dense{ElT1,CuVector{ElT1}}},
                           ::Type{ElT2}) where {ElT1,
                                                ElT2<:Number}
  ElR  = promote_type(ElT1,ElT2)
  VecR = CuVector{ElR}
  return Dense{ElR,VecR}
end

function Base.permutedims(T::CuDenseTensor{<:Number,N},
                          perm::NTuple{N,Int}) where {N}
  Tp = similar(T,permute(inds(T),perm))
  permute!(Tp,T)
  return Tp
end

function Base.permutedims!(R::CuDenseTensor{<:Number,N},
                           T::CuDenseTensor{<:Number,N},
                           perm::NTuple{N,Int}) where {N}
    return permutedims!!(R, T, perm)
end

function permutedims!!(B::Tensor{ElT,N,StoreT,IndsB},
                       A::Tensor{ElT,N,StoreT,IndsA},
                       perm::NTuple{N,Int},
                       f::Function=(r,t)->permute!(r,t)) where {N,ElT,IndsB,IndsA,StoreT<:CuDense{ElT}}
  Ais = inds(A)
  Bis = permute(inds(A), perm)
  B = f(B, A)
  return B
end

function Base.similar(::Type{<:CuDenseTensor{ElT}},
                      inds) where {ElT}
    storage_arr = CuVector{ElT}(undef,dim(inds))
    return Tensor(Dense(storage_arr),inds)
end

function outer!(R::CuDenseTensor,
                T1::CuDenseTensor,
                T2::CuDenseTensor)
  R_dat = vec(array(T1))*transpose(vec(array(T2)))
  copyto!(data(store(R)), vec(R_dat))
  inds_outer = unioninds(inds(T1),inds(T2))
  return R
end

function contract!!(R::CuDenseTensor{<:Number,NR},
                    labelsR::NTuple{NR},
                    T1::CuDenseTensor{<:Number,N1},
                    labelsT1::NTuple{N1},
                    T2::CuDenseTensor{<:Number,N2},
                    labelsT2::NTuple{N2}) where {NR,N1,N2}
  if N1==0
    # TODO: replace with an add! function?
    # What about doing `R .= T1[] .* PermutedDimsArray(T2,perm)`?
    perm = getperm(labelsR,labelsT2)
    newT2 = Tensor(Dense(data(store(T1)).*data(store(T2))), inds(T2))
    permute!(R,newT2)
  elseif N2==0
    perm = getperm(labelsR,labelsT1)
    newT1 = Tensor(Dense(data(store(T2)).*data(store(T1))), inds(T1))
    permute!(R,newT1)
  elseif N1+N2==NR
    # TODO: permute T1 and T2 appropriately first (can be more efficient
    # then permuting the result of T1⊗T2)
    # TODO: implement the in-place version directly
    R = outer!!(R,T1,T2)
    inds_outer = unioninds(inds(T1),inds(T2))
    R = Tensor(store(R), inds_outer)
  else
    R = _contract!!(R,labelsR,T1,labelsT1,T2,labelsT2)
  end
  return R
end

function permutedims!!(B::CuDenseTensor{ElT,0},
                       A::CuDenseTensor{ElT,0},
                       perm::NTuple{0,Int},
                       f=(r,t)->permute!(r,t)) where {ElT<:Number}
    Cs = f(B, A)
    return Tensor(Dense(vec(Cs)), IndexSet{0}())
end

function permutedims!!(B::CuDenseTensor{ElT,N},
                       A::CuDenseTensor{ElT,0},
                       perm::NTuple{N,Int},
                       f=(r,t)->permute!(r,t)) where {N, ElT<:Number}
    Cis = permute(inds(B), perm)
    Cs = f(B, A)
    return Tensor(Dense(vec(Cs)), Cis)
end

function _contract!(CT::CuDenseTensor{El,NC},
                    AT::CuDenseTensor{El,NA},
                    BT::CuDenseTensor{El,NB},
                    props::ContractionProperties,
                    α::Number=one(El),β::Number=zero(El)) where {El,NC,NA,NB}
  Ainds = inds(AT)
  Adims = dims(Ainds)
  Binds = inds(BT)
  Bdims = dims(Binds)
  Cinds = inds(CT)
  Cdims = dims(Cinds)
  Adata = reshape(data(store(AT)),Adims)
  Bdata = reshape(data(store(BT)),Bdims)
  Cdata = reshape(data(store(CT)),Cdims)
  contracted = commoninds(Ainds, Binds)
  A_only = uniqueinds(Ainds, Binds)
  B_only = uniqueinds(Binds, Ainds)
  ind_dict = Vector{Index}()
  for (idx, i) in enumerate(contracted)
      push!(ind_dict, i)
  end
  if length(A_only) > 0
      for (idx, i) in enumerate(A_only)
          push!(ind_dict, i)
      end
  end
  if length(B_only) > 0
      for (idx, i) in enumerate(B_only)
          push!(ind_dict, i)
      end
  end
  ctainds = zeros(Int, length(Ainds))
  ctbinds = zeros(Int, length(Binds))
  ctcinds = zeros(Int, length(Cinds))
  for (ii, ia) in enumerate(Ainds)
      ctainds[ii] = findfirst(x->x==ia, ind_dict)
  end
  for (ii, ib) in enumerate(Binds)
      ctbinds[ii] = findfirst(x->x==ib, ind_dict)
  end
  for (ii, ic) in enumerate(Cinds)
      ctcinds[ii] = findfirst(x->x==ic, ind_dict)
  end
  id_op    = CuArrays.CUTENSOR.CUTENSOR_OP_IDENTITY
  dict_key = ""
  for cc in zip(ctcinds, Cdims)
      dict_key *= string(cc[1]) * "," * string(cc[2]) * ","
  end
  for aa in zip(ctainds, Adims)
      dict_key *= string(aa[1]) * "," * string(aa[2]) * ","
  end
  for bb in zip(ctbinds, Bdims)
      dict_key *= string(bb[1]) * "," * string(bb[2]) * ","
  end
  if haskey(ENV, "CUTENSOR_AUTOTUNE") && tryparse(Int, ENV["CUTENSOR_AUTOTUNE"]) == 1
      if haskey(ContractionPlans, dict_key)
          dict_val = ContractionPlans[dict_key]
          algo  = dict_val
          #plan  = dict_val[2]
          Cdata = CuArrays.CUTENSOR.contraction!(α, Adata, Vector{Char}(ctainds), id_op, Bdata, Vector{Char}(ctbinds), id_op, β, Cdata, Vector{Char}(ctcinds), id_op, id_op; algo=algo)
      else
          # loop through all algos
          # pick the fastest one
          # store that plan!
          best_time = 1e6
          best_plan = nothing
          best_algo = nothing
          max_algos = Ref{Int32}(C_NULL)
          CuArrays.CUTENSOR.cutensorContractionMaxAlgos(max_algos)
          # fix once the other options are documented
          #algos = collect(Cint(CuArrays.CUTENSOR.CUTENSOR_ALGO_GETT):Cint(max_algos[] - 1))
          algos = collect(Cint(CuArrays.CUTENSOR.CUTENSOR_ALGO_GETT):Cint(-1))
          for algo in reverse(algos)
              try
                  #this_plan = CuArrays.CUTENSOR.contraction_plan(Adata, Vector{Char}(ctainds), id_op, Bdata, Vector{Char}(ctbinds), id_op, Cdata, Vector{Char}(ctcinds), id_op, id_op; algo=CuArrays.CUTENSOR.cutensorAlgo_t(algo), pref=CuArrays.CUTENSOR.CUTENSOR_WORKSPACE_MAX)
                  Cdata, this_time, bytes, gctime, memallocs = @timed CuArrays.CUTENSOR.contraction!(α, Adata, Vector{Char}(ctainds), id_op, Bdata, Vector{Char}(ctbinds), id_op, β, Cdata, Vector{Char}(ctcinds), id_op, id_op; algo=CuArrays.CUTENSOR.cutensorAlgo_t(algo))
                  if this_time < best_time
                      best_time = this_time
                      #best_plan = this_plan
                      best_algo = CuArrays.CUTENSOR.cutensorAlgo_t(algo)
                  end
              catch err
                  @warn "Algorithm $algo not supported"
              end
          end
          ContractionPlans[dict_key] = best_algo
      end
  else
      Cdata = CuArrays.CUTENSOR.contraction!(α, Adata, Vector{Char}(ctainds), id_op, Bdata, Vector{Char}(ctbinds), id_op, β, Cdata, Vector{Char}(ctcinds), id_op, id_op)
  end
  return parent(Cdata)
end

function Base.:+(B::CuDenseTensor, A::CuDenseTensor)
  opC  = CUTENSOR.CUTENSOR_OP_IDENTITY
  opA  = CUTENSOR.CUTENSOR_OP_IDENTITY
  opAC = CUTENSOR.CUTENSOR_OP_ADD
  Ais = inds(A)
  Bis = inds(B)
  ind_dict = Vector{Index}()
  for (idx, i) in enumerate(inds(A))
      push!(ind_dict, i)
  end
  Adata = data(store(A))
  Bdata = data(store(B))
  reshapeBdata = reshape(Bdata,dims(Bis))
  reshapeAdata = reshape(Adata,dims(Ais))
  ctainds = zeros(Int, length(Ais))
  ctbinds = zeros(Int, length(Bis))
  for (ii, ia) in enumerate(Ais)
      ctainds[ii] = findfirst(x->x==ia, ind_dict)
  end
  for (ii, ib) in enumerate(Bis)
      ctbinds[ii] = findfirst(x->x==ib, ind_dict)
  end
  ctcinds = copy(ctbinds)
  C = CuArrays.zeros(eltype(Bdata), dims(Bis))
  CUTENSOR.elementwiseBinary!(one(eltype(Adata)), reshapeAdata, ctainds, opA, one(eltype(Bdata)), reshapeBdata, ctbinds, opC, C, ctcinds, opAC)
  copyto!(data(store(B)), vec(C))
  return B
end

function Base.:+(B::CuDense, Bis::IndexSet, A::CuDense, Ais::IndexSet)
  opA  = CUTENSOR.CUTENSOR_OP_IDENTITY
  opC  = CUTENSOR.CUTENSOR_OP_IDENTITY
  opAC = CUTENSOR.CUTENSOR_OP_ADD
  ind_dict = Vector{Index}()
  for (idx, i) in enumerate(Ais)
      push!(ind_dict, i)
  end
  Adata = data(A)
  Bdata = data(B)
  reshapeBdata = reshape(Bdata,dims(Bis))
  reshapeAdata = reshape(Adata,dims(Ais))
  ctainds = zeros(Int, length(Ais))
  ctbinds = zeros(Int, length(Bis))
  for (ii, ia) in enumerate(Ais)
      ctainds[ii] = findfirst(x->x==ia, ind_dict)
  end
  for (ii, ib) in enumerate(Bis)
      ctbinds[ii] = findfirst(x->x==ib, ind_dict)
  end
  ctcinds = copy(ctbinds)
  C = CuArrays.zeros(eltype(Bdata), dims(Bis))
  Cis = Bis
  C = CUTENSOR.elementwiseBinary!(1, reshapeAdata, ctainds, opA, 1, reshapeBdata, ctbinds, opC, C, ctcinds, opAC)
  copyto!(data(B), vec(C))
  return C
end

function Base.:-(B::CuDenseTensor, A::CuDenseTensor)
  opC  = CUTENSOR.CUTENSOR_OP_IDENTITY
  opA  = CUTENSOR.CUTENSOR_OP_IDENTITY
  opAC = CUTENSOR.CUTENSOR_OP_ADD
  Ais = inds(A)
  Bis = inds(B)
  ind_dict = Vector{Index}()
  for (idx, i) in enumerate(inds(A))
      push!(ind_dict, i)
  end
  Adata = data(store(A))
  Bdata = data(store(B))
  reshapeBdata = reshape(Bdata,dims(Bis))
  reshapeAdata = reshape(Adata,dims(Ais))
  ctainds = zeros(Int, length(Ais))
  ctbinds = zeros(Int, length(Bis))
  for (ii, ia) in enumerate(Ais)
      ctainds[ii] = findfirst(x->x==ia, ind_dict)
  end
  for (ii, ib) in enumerate(Bis)
      ctbinds[ii] = findfirst(x->x==ib, ind_dict)
  end
  ctcinds = copy(ctbinds)
  C = CuArrays.zeros(eltype(Bdata), dims(Bis))
  CUTENSOR.elementwiseBinary!(one(eltype(Adata)), reshapeAdata, ctainds, opA, -one(eltype(Bdata)), reshapeBdata, ctbinds, opC, C, ctcinds, opAC)
  copyto!(data(store(B)), vec(C))
  return B
end

function Base.:-(A::CuDense, Ais::IndexSet, B::CuDense, Bis::IndexSet)
  opA  = CUTENSOR.CUTENSOR_OP_IDENTITY
  opC  = CUTENSOR.CUTENSOR_OP_IDENTITY
  opAC = CUTENSOR.CUTENSOR_OP_ADD
  ind_dict = Vector{Index}()
  for (idx, i) in enumerate(Ais)
      push!(ind_dict, i)
  end
  Adata = data(A)
  Bdata = data(B)
  reshapeBdata = reshape(Bdata,dims(Bis))
  reshapeAdata = reshape(Adata,dims(Ais))
  ctainds = zeros(Int, length(Ais))
  ctbinds = zeros(Int, length(Bis))
  for (ii, ia) in enumerate(Ais)
      ctainds[ii] = findfirst(x->x==ia, ind_dict)
  end
  for (ii, ib) in enumerate(Bis)
      ctbinds[ii] = findfirst(x->x==ib, ind_dict)
  end
  ctcinds = copy(ctbinds)
  C = CuArrays.zeros(eltype(Bdata), dims(Bis))
  Cis = Bis
  C = CUTENSOR.elementwiseBinary!(one(eltype(Adata)), reshapeAdata, ctainds, opA, -one(eltype(Bdata)), reshapeBdata, ctbinds, opC, C, ctcinds, opAC)
  copyto!(data(B), vec(C))
  return C
end

function Base.permute!(B::CuDenseTensor, A::CuDenseTensor)
  Ais = inds(A)
  Bis = inds(B)
  ind_dict = Vector{Index}()
  for (idx, i) in enumerate(Ais)
      push!(ind_dict, i)
  end
  Adata = data(store(A))
  Bdata = data(store(B))
  reshapeBdata = reshape(Bdata,dims(Bis))
  reshapeAdata = reshape(Adata,dims(Ais))
  ctainds = zeros(Int, length(Ais))
  ctbinds = zeros(Int, length(Bis))
  for (ii, ia) in enumerate(Ais)
      ctainds[ii] = findfirst(x->x==ia, ind_dict)
  end
  for (ii, ib) in enumerate(Bis)
      ctbinds[ii] = findfirst(x->x==ib, ind_dict)
  end

  CuArrays.CUTENSOR.permutation!(one(eltype(Adata)), reshapeAdata, Vector{Char}(ctainds), reshapeBdata, Vector{Char}(ctbinds))
  return vec(reshapeBdata)
end

function Base.permute!(B::CuDense, Bis::IndexSet, A::CuDense, Ais::IndexSet)
  ind_dict = Vector{Index}()
  for (idx, i) in enumerate(Ais)
      push!(ind_dict, i)
  end
  Adata = data(A)
  Bdata = data(B)
  reshapeBdata = reshape(Bdata,dims(Bis))
  reshapeAdata = reshape(Adata,dims(Ais))
  ctainds = zeros(Int, length(Ais))
  ctbinds = zeros(Int, length(Bis))
  for (ii, ia) in enumerate(Ais)
      ctainds[ii] = findfirst(x->x==ia, ind_dict)
  end
  for (ii, ib) in enumerate(Bis)
      ctbinds[ii] = findfirst(x->x==ib, ind_dict)
  end

  CuArrays.CUTENSOR.permutation!(one(eltype(Adata)), reshapeAdata, Vector{Char}(ctainds), reshapeBdata, Vector{Char}(ctbinds))
  return vec(reshapeBdata)
end


text:
# Actual scattering function
########################################################
########################################################

function (stPara::stParallel)(x; nonlinearity = abs, thin = false,
    outputSubsample = (-1, -1), subsam = true,
    totalScales = [-1 for i = 1:depth(stPara)+1],
    percentage = 0.9, fftPlans = -1)
    st(x, stPara, nonlinearity; thin = thin, outputSubsample = outputSubsample,
        subsam = subsam, totalScales = totalScales, percentage = percentage,
        fftPlans = fftPlans)
end

# TODO: make a function which determines the breakpoints given the layers function and the size of the input
# TODO: non-thin is currently not outputing values in the data section
@doc """
see the docs for stParallel
"""
function st(X::AbstractArray{T,N}, layers::stParallel, nonlinear::nl;
    fullOr::fullType = fullType(),# subsam::Sub = bspline(), #TODO
    # allow for variation in subsamping method again
    thin::Bool = true, outputSubsample::Tuple{Int,Int} = (-1, -1),
    subsam::Bool = true, totalScales = [-1 for i = 1:depth(layers)+1],
    percentage = 0.9, fftPlans = -1) where {T<:Real,S<:Union,N,nl<:Function,Sub<:resamplingMethod}
    @assert length(totalScales) == depth(layers) + 1
    @assert fftPlans == -1 || typeof(fftPlans) <: Array{<:Future,2}
    if T <: Float64
        @warn "data type is $T. This is probably higher precision than you need and likely to eat a lot of memory"
    end
    dataDim = eltypes(layers)[2]
    # Insist that X has to have at least one extra meta-dimension, even if it is 1
    if ndims(X) == dataDim
        X = reshape(X, (size(X)..., 1))
    end
    numChildλ = 0
    n, q, dataSizes, outputSizes, resultingSize =
        calculateSizes(layers, outputSubsample, size(X), totalScales = totalScales, percentage = percentage)

    nextData = [reshape(X, (size(X)[1:dataDim]..., 1, size(X)[(dataDim+1):end]...))]
    @debug "about to make the storage arrays"

    # get the size of a single entry as a single vector (outputSizes gives the
    # # of paths)
    netSize = Int(sum([resultingSize[i] * x[dataDim+1] for (i, x) in
                       enumerate(outputSizes)])...)
    @debug "netSize = $(netSize), resultingSize=$(resultingSize), outputSizes=$(outputSizes)"

    # create list of size references if we're subsampling the output an
    # extra amount
    results = SharedArray(zeros(T, netSize, outputSizes[1][dataDim+2:end]...))
    @debug "outputSizes = $(outputSizes)"
    @debug "made the storage arrays, about to make the fft plans"

    if fftPlans == -1
        @debug "dataSizes = $(dataSizes)"
        fftPlans = createFFTPlans(layers, dataSizes, T = T, iscomplex = T <: Complex)
    end
    @debug "about to start iterating"
    results = iterateOverLayers!(layers, results, nextData, dataSizes,
        outputSizes, dataDim, q, totalScales, T, thin,
        nonlinear, subsam, outputSubsample,
        resultingSize, fftPlans)
    @debug "finished iterate Over layers"

    if thin
        return results
    else
        return rollSt(layers, results, X; percentage = percentage,
            outputSubsample = outputSubsample)
    end
end
function st(layers::stParallel, X::AbstractArray{T,N}, nonlinear::nl;
    fullOr::fullType = fullType(),# subsam::Sub = bspline(), #TODO
    # allow for variation in subsamping method again
    thin::Bool = true, outputSubsample::Tuple{Int,Int} = (-1, -1),
    subsam::Bool = true, totalScales = [-1 for i = 1:depth(layers)+1],
    percentage = 0.9, fftPlans = -1) where {T<:Real,S<:Union,N,nl<:
    Function,Sub<:resamplingMethod}
    return st(X, layers, nonlinear, fullOr, thin = thin,
        outputSubsample = outputSubsample, subsam = subsam, totalScales = totalScales, percentage = percentage)
end
st(layers::stParallel, X::Array{T}; nonlinear::Function = abs, subsam = true) where {T<:Real} = st(X, layers, nonlinear, subsam = subsam)

function iterateOverLayers!(layers, results, nextData, dataSizes, outputSizes,
    dataDim, q, totalScales, T, thin, nonlinear, subsam,
    outputSubsample, resultingSize, fftPlans)
    for (i, layer) in enumerate(layers.shears[1:depth(layers)])
        @debug "On layer $(i)"
        @debug "size(nextData) = $(size(nextData[1]))"
        cur = nextData # data from the previous layer

        # only store the intermediate results in intermediate layers
        # TODO: get rid of the data channel, or replace nextData with it
        if i < depth(layers)
            # store the data in a channel, along with the number of
            # it's parent
            dataChannel = Channel{Tuple{Array{length(dataSizes[i+1])},Int64}}(size(cur)[end])
            filler = SharedArray(zeros(T, [1 for i = 1:length(dataSizes[1])]...))
            nextData = SharedArray[filler for i = 1:size(cur[1])[dataDim+1]*length(cur)]
        end

        @debug "cur = $(typeof(cur)), $(size(cur))"
        innerAxes = axes(cur[1])[1:dataDim] # effectively a
        # set of colons of length dataDim, to be used for input
        @debug "innerAxes= $(innerAxes)"
        innerSub = (Base.OneTo(x) for x in
                    dataSizes[i+1][1:dataDim]) # effectively a
        # set of colons of length dataDim, to be used for the
        # subsampled output

        outerAxes = axes(cur[1])[(dataDim+2):end] # the same idea as
        # innerAxes, but for the example indices
        @debug "outerAxes= $(outerAxes)"
        wev = 3
        # precompute the wavelets and the fft plan
        if dataDim == 1
            @debug "earlier layer $(i)"
            @debug "size(cur[1]) = $(size(cur[1]))"
            daughters, ω = computeWavelets(size(cur[1], 1),
                layers.shears[i];
                T = eltype(cur[1]), nScales = -1)
            @debug "size of daughters = $(size(daughters))"
            concatStart = reduce(+,
                q[1:i-1] .* resultingSize[1:i-1],
                init = 0) + 1
            # create an array for the fftPlan
            padBy = (0, 0)
        else
            concatStart = sum([prod(oneLayer[1:3]) for oneLayer in
                               outputSizes[1:i-1]]) + 1
            daughters = []
            padBy = getPadBy(layers.shears[i])
        end

        listOfProcessResults = Array{Future,1}(undef,
            size(cur[1])[dataDim+1] * length(cur))
        @debug "size of list = $(size(listOfProcessResults)), because " *
               "$(size(cur[1])[dataDim + 1]) and $(length(cur))"
        # parallel processing tools; the results are spread over the previous 2
        # layers paths

        # iterate over the scales two layers back
        if i == depth(layers)
            # compute the final mother if we're on the last layer
            if dataDim == 1
                @debug "last layer dataSizes[end] = $(dataSizes[end]), $(layers.shears[i + 1])"
                finalDaughters, ω = computeWavelets(dataSizes[end][1],
                    layers.shears[i+1]; nScales = 1)
                @debug "size of finalDaughters = $(size(finalDaughters))"
                concatStartLast = reduce(+, (q.*resultingSize)[1:end-1], init = 0) + 1
                @debug "concatStartLast = $(concatStartLast)"
                padByLast = (1, 3)
                nScalesLastLayer = size(daughters, 2) - 1
            else
                mother = []
                finalDaughters = []
                concatStartLast = sum([prod(oneLayer[1:3]) for oneLayer
                                       in
                                       outputSizes[1:end-1]]) + 1
                padByLast = getPadBy(layers.shears[end])
                nScalesLastLayer = q[end]
            end
            spawningJobs!(listOfProcessResults, layers, results, cur,
                outerAxes, innerAxes, innerSub, dataDim, i,
                daughters, finalDaughters, totalScales[i], nonlinear,
                subsam, outputSubsample, outputSizes, resultingSize,
                concatStart, concatStartLast, padBy, padByLast,
                nScalesLastLayer, fftPlans, T, dataSizes)
        else
            # any layer before the penultimate
            spawningJobs!(listOfProcessResults, layers, results, cur,
                dataSizes, outerAxes, innerAxes, innerSub, dataDim, i,
                daughters, totalScales[i], nonlinear, subsam,
                outputSubsample, outputSizes[i], concatStart, padBy,
                resultingSize, dataChannel, fftPlans, T)
        end
        # using one channel per
        for (λ, x) in enumerate(listOfProcessResults)
            @debug "type of the thing being fetched: $typeof(x)"
            tmpFetch = fetch(x)
            if typeof(tmpFetch) <: Exception
                throw(tmpFetch)
            end
            if i < depth(layers)
                nextData[λ] = tmpFetch
            end
        end
        @debug "fetched from workers"
    end
    results
end

# the midlayer version, i.e. i≠m
function spawningJobs!(listOfProcessResults, layers, results, cur, dataSizes,
    outerAxes, innerAxes, innerSub, dataDim, i, daughters,
    totalScale, nonlinear, subsam, outputSubsample,
    outputSize, concatStart, padBy, resultingSize,
    dataChannel, fftPlans, T)
    njobs = Distributed.nworkers()
    cjob = 0
    for (j, x) in enumerate(cur)
        # iterate over all paths in layer i
        @debug "siz =$(size(x, dataDim + 1))"
        for λ = 1:size(x, dataDim + 1)
            # do the actual transformation; the last layer requires
            # far less saved than the mid-layers. cjob+1 is the worker to
            # assign the task to (+1 since mod is 0...n-1 rather than 1...n
            @debug "sending out remotecalls"
            futureThing = remotecall(midLayer!, cjob + 1, layers, results, x,
                dataSizes, outerAxes, innerAxes, innerSub,
                dataDim, i, daughters, totalScale,
                nonlinear, subsam, outputSubsample,
                outputSize, concatStart, padBy, λ,
                resultingSize, dataChannel,
                fftPlans[cjob+1, i], T)
            cjob = mod(cjob + 1, njobs)
            if typeof(futureThing) <: typeof(Distributed.RemoteException)
                throw(futureThing)
            else
                @debug "writing to $((j - 1) * size(cur[1])[end] + λ) in listofProcessResults"
                listOfProcessResults[(j-1)*size(cur[1])[dataDim+1]+λ] = futureThing
            end
        end
    end
end

# the end version, i.e. i=m

function spawningJobs!(listOfProcessResults, layers, results, cur, outerAxes,
    innerAxes, innerSub, dataDim, i, daughters,
    finalDaughters, totalScale, nonlinear, subsam,
    outputSubsample, outputSizes, resultingSize,
    concatStart, concatStartLast, padBy, padByLast,
    nScalesLastLayer, fftPlans, T, dataSizes)
    njobs = Distributed.nworkers()
    cjob = 0
    for (j, x) in enumerate(cur)
        # iterate over all paths in layer i
        for λ = 1:size(x, dataDim + 1)
            # do the actual transformation; the last layer requires
            # far less saved than the mid-layers

            futureThing = remotecall(finalLayer!, cjob + 1, layers, results, x,
                outerAxes, innerAxes, innerSub, dataSizes,
                dataDim, i, daughters, finalDaughters,
                totalScale, nonlinear, subsam,
                outputSubsample, outputSizes, λ,
                resultingSize, concatStart,
                concatStartLast, padBy, padByLast,
                nScalesLastLayer, fftPlans[cjob+1,
                    i], fftPlans[cjob+1, i+1], T)

            cjob = mod(cjob + 1, njobs)
            if typeof(futureThing) <: typeof(Distributed.RemoteException)
                throw(futureThing)
            else
                listOfProcessResults[(j-1)*size(cur[1])[end]+λ] = futureThing
            end

        end
    end
    return listOfProcessResults
end

@doc """
        midLayer!(layers, results, cur, dataSize, outerAxes, innerAxes, innerSub, dataDim, i, daughters, nScales, nonlinear, subsam, outputSubsample, concatStart, λ)
        midLayer!(layers, results, cur, nextData, outerAxes, innerAxes, innerSub, outerAxes, dataDim, i, nScalesLayers, daughters, nScales, nonlinear, subsam, outputSubsample,
     λ, keeper)
    An intermediate function which takes a single path in a layer and generates all of the children of that path in the next layer. Only to be used on intermediate layers, as finalLayerTransform fills the same role in the last layer. If keeper is omitted, it assumes we don't have decreasing type, otherwise it's assumed

"""
function midLayer! end

viableDims = [(1, cwt)]
function midLayer!(layers::stParallel{K,1}, results, curPath, dataSizes,
    outerAxes, innerAxes, innerSub, dataDim, i, daughters,
    nScales, nonlinear, subsam, outputSubsample,
    outputSizeThisLayer, concatStart, padBy, λ, resultingSize,
    homeChannel, fftPlan, T) where {K}
    # make an array to return the results
    @debug "dataSizes = $dataSizes"
    toBeHandedBack = zeros(T, dataSizes[i+1][1:dataDim]...,
        size(daughters, 2) - 1,
        dataSizes[i+1][dataDim+2:end]...)
    @debug "size(toBeHandedBack) = $(size(toBeHandedBack))"
    # toBeHandedBack = SharedArray{T}(dataSizes[i+1][1:end-1]...,
    #                                    size(daughters,2)-1; pids=procs())
    # first perform the continuous wavelet transform on the data from the
    # previous layer
    output = cwt(view(curPath, innerAxes..., λ, outerAxes...), layers.shears[i],
        daughters, fftPlan)
    @debug "" size(output)
    innerMostAxes = axes(output)[end:end]
    # iterate over the non transformed dimensions of output
    writeLoop!(output, outerAxes, i, T, dataSizes, innerAxes, innerSub, layers,
        results, toBeHandedBack, concatStart, λ, dataDim, nothing,
        nonlinear, subsam, outputSizeThisLayer, outputSubsample,
        resultingSize)
    @debug "AFTER writeloop in midlayer size(toBeHandedBack) = $(size(toBeHandedBack))"
    return toBeHandedBack
end

function writeLoop!(output, outerAxes, i, T, dataSizes, innerAxes,
    innerSub, layers, results, toBeHandedBack,
    concatStart, λ, dataDim, outputSize,
    nonlinear, subsam, outputSizeThisLayer,
    outputSubsample, resultingSize)
    for outer in eachindex(view(output, [1 for i = 1:(dataDim+1)]...,
        outerAxes...))
        # output may have length zero if the starting path has low
        # enough scale
        for j = 2:size(output, dataDim + 1)
            toBeHandedBack[innerSub..., j-1, outer] =
                nonlinear.(resample(view(output, innerAxes..., j,
                        outer), layers.subsampling[i]))
        end
        # actually write to the output
        if subsam
            tmpOut = Array{T,dataDim}(real.(resample(view(output,
                    innerAxes...,
                    1,
                    outer),
                0.0f0, newSize = outputSizeThisLayer[1:dataDim])))
        else
            tmpOut = Array{T,dataDim}(real(resample(view(output,
                    innerAxes...,
                    1,
                    outer),
                layers.subsampling[i])))
        end
        sizeTmpOut = prod(size(tmpOut))
        if outputSubsample[1] > 1 || outputSubsample[2] > 1
            @debug "(λ-1)*resultingSize[i] = $((λ - 1) * resultingSize[i])"
            resampled = resample(tmpOut, 0.0f0, newSize = resultingSize[i])
            results[concatStart.+(λ-1)*resultingSize[i].+(0:(resultingSize[i]-1)), outer] =
                resample(tmpOut, 0.0f0, newSize = resultingSize[i])
        else
            results[concatStart.+(λ-1)*resultingSize[i].+(0:sizeTmpOut-1), outer] = reshape(tmpOut, (sizeTmpOut))
        end
        @debug "λ = $(λ), i=$(i), concatStart = $(concatStart)"
    end
end

@doc """
        finalLayer!(layers, results, curPath, outerAxes, innerAxes, innerSub, dataDim, i, daughters, nScales, nonlinear, subsam, outputSubsample, λ, resultingSize, concatStart, λ)
Do the transformation of the m-1 to mth layer, the output of the m-1st layer, and the output of the mth layer. These are glued together for mostly for computational reasons. There is currently no decreasing paths version, so it should end up throwing errors
"""
function finalLayer!(layers::stParallel{K,N}, results, curPath,
    outerAxes, innerAxes, innerSub, dataSizes, dataDim, i,
    daughters, finalDaughters, nScales, nonlinear,
    subsam, outputSubsample, outputSizes, λ, resultingSize,
    concatStart, concatStartLast, padBy, padByLast,
    nScalesLastLayer, fftPlan, fftPlanFinal, T) where {K,N}
    # iterate over the outerAxes
    # first perform the continuous wavelet transform on the data from the
    # previous layer
    @debug "inner = $(innerAxes), outer = $(outerAxes), size(curPath) = " *
           "$(size(curPath))"
    @debug "starting,λ=$(λ) in finalLayer!"
    output = dispatch(N, view(curPath, innerAxes..., λ, outerAxes...),
        layers.shears[i], daughters, fftPlan)

    @debug "starting, $innerAxes"
    nScalesPenult = getLastScales(dataDim, daughters, layers.shears[i])# numScales(layers.shears[i], size(innerAxes[1],1), i)
    toBeHandedOnwards = zeros(T, dataSizes[end][1:dataDim]...,
        nScalesPenult, dataSizes[end][3:end]...)
    @debug "handing onwards"
    writeLoop!(output, outerAxes, i, T, dataSizes, innerAxes, innerSub, layers,
        results, toBeHandedOnwards, concatStart, λ, dataDim, nothing,
        nonlinear, subsam, outputSizes[end-1], outputSubsample,
        resultingSize)
    @debug "writeLoop"
    innerAxes = axes(toBeHandedOnwards)[1:dataDim]
    # write the output from the mth layer to output
    tmpSize = 1
    for j = 2:size(output, dataDim + 1)
        finalOutput = averaging(dataDim, view(toBeHandedOnwards, innerAxes..., j - 1,
                outerAxes...), layers.shears[i+1],
            finalDaughters, fftPlanFinal)
        for outer in eachindex(view(finalOutput, [1 for i = 1:dataDim]...,
            outerAxes...))
            tmpFinal = Array{T,dataDim}(real.(resample(finalOutput[innerAxes...,
                    outer],
                0.0f0, newSize = outputSizes[end][1:dataDim])))
            if outputSubsample[1] > 1 || outputSubsample[2] > 1
                results[concatStartLast+
                        (λ-1)*nScalesLastLayer*resultingSize[end]+
                        (j-2)*resultingSize[i+1].+(0:(resultingSize[i+1]-1)),
                    outer] = resample(tmpFinal, 0.0f0, newSize = resampleTo(dataDim, resultingSize,
                    outputSizes, i))
            else
                sizeTmpOut = prod(size(tmpFinal))
                tmpSize = sizeTmpOut
                results[(concatStartLast+
                         (λ-1)*nScalesLastLayer*resultingSize[end]+
                         (j-2)*resultingSize[i+1]).+(0:(sizeTmpOut-1)),
                    outer] = reshape(tmpFinal, (sizeTmpOut))
            end
        end
    end
end

resampleTo(dataDim, resultingSize, outputSizes, i) = dataDim == 1 ?
                                                     resultingSize[i+1] : outputSizes[i+1][2]

ext: jl


text:
#
# TODO:
# - Clear excess whitespace.
# - Configuration validation.
#
type Configuration
  parameters::Dict{String, String}
  types::Vector{String}
  instructions::Vector{String}

  Configuration() = new(Dict{String, Any}(), String[], Symbol[])
end

# Loads a configuration file at a given location.
load_configuration(f::String) = open(load_configuration, f)
function load_configuration(f::IOStream)
  c = Configuration()
  for ln in eachline(f)
    ln = strip(ln)

    # Ignore comments and empty lines.
    if !isempty(ln) && ln[1] != '#'
      k, v = split(ln)
      if k == "type" # Type declaration.
        push!(c.types, v)
      elseif k == "instruction" # Instruction declaration.
        push!(c.instructions, v)
      else # Parameter definition.
        c.parameters[k] = v
      end
    end
  end
  return c
end

# Creates and returns an initial state using a given configuration.
configure(f::String) = configure(load_configuration(f))
function configure(c::Configuration)
  s = State()

  # Instruction handling.
  for i in c.instructions
    enable_instruction!(s, i)
  end

  # Type handling.
  # - Means nothing for now.

  # Parameter handling.
  set!(s.parameters, c.parameters)

  return s
end


text:
"""
Structures and functions for the EXPLICIT POMDPs.jl interface of the Pricing MDP
"""

"""
Enumerates all states for MDP
"""
function generate_states(pp::PMDPProblem)::AbstractArray{<:State}
    c_it = Iterators.product([0:cᵣ for cᵣ in pp.c₀]...)
    s_it = Iterators.product(c_it, 1:selling_period_end(pp), 1:(n_products(pp)+1)) # +1 for empty_product
    states = [State(SVector(args[1]...), args[2], args[3]) for args in s_it]
end

function stateindices(pp::PMDPProblem)::LinearIndices
    C_sizes = pp.c₀ .+ 1                # +1 for 0 capacity
    T_size = selling_period_end(pp)     # timestep starts at t=1 and goes up to t=T
    prd_sizes = n_products(pp)+1        # +1 for empty product

    LinearIndices((C_sizes..., T_size, prd_sizes))
end

"""
m = PMDPe(edges, products, λ)

PMDP for explicit interface
"""
struct PMDPe <: PMDP{State, Action}
    pp::PMDPProblem
    empty_product::Product
    empty_product_id::Int64
    statelinearindices::LinearIndices # ONLY FOR EXPLICIT, replaces need for states array
    # stage_statelinearindices::LinearIndices

    function PMDPe(pp::PMDPProblem)
        sli = stateindices(pp)
        return new(pp, empty_product(pp), n_products(pp)+1, sli)
    end
end

"""
Works only for un-empty product
"""
function sale_prob(budget_distributions::AbstractArray{<:Distribution}, s::State, a::Action)
    # cdf is probabulity that the sample from distribution is below or equal (≤) the asking price a
    # we want probability that sample is below the asking price (<).
    # This is only issue with discrete distributions, for those, I will subtract ϵ from a.
    1-cdf(budget_distributions[s.iₚ], a-ϵ)
end

function next_states(m::PMDP, s::State, new_c::AbstractArray{<:Number})::Array{State}
    sps = [State(new_c, s.t+1, iₚ) for iₚ in 1:n_products(m)+1] # +1 for empty_product
end

function POMDPs.transition(m::PMDPe, s::State, a::Action)
    # --- Request arrival probs
    product_request_probs = demand(m)[s.t].p

    # NEXT STATES
    # if s.t == selling_period_end(m)
    #     sps = [s]
    #     probs = [1.]
    if sale_impossible(m, s, a)
        sps = next_states(m, s, s.c)
        probs = product_request_probs
    else # sale possible
        prob_sale = sale_prob(budgets(m), s, a)

        # sufficient capacity for sale and non-empty request
        sps_nosale = next_states(m, s, s.c)
        probs_nosale = product_request_probs .* (1-prob_sale)

        sps_sale = next_states(m, s, s.c-product(m, s))
        probs_sale = product_request_probs .* prob_sale

        sps = vcat(sps_nosale, sps_sale)
        probs = vcat(probs_nosale, probs_sale)
    end

    @assert sum(probs) ≈ 1.

    return SparseCat(sps, probs)
end

function POMDPs.reward(m::PMDPe, s::State, a::Action, sp::State)
    if objective(m) == :revenue
        s.c==sp.c ? 0. :  a
    elseif objective(m) == :utilization
        s.c==sp.c ? 0. :  sum(product(m, s))
    end
end

function POMDPs.stateindex(m::PMDPe, s::State)
    ci = CartesianIndex((s.c .+ 1)..., s.t, s.iₚ) # +1 for capacity because capaciteus go from 0..c₀
    m.statelinearindices[ci]
end

POMDPs.actionindex(m::PMDP, a::Action) = findfirst(isequal(a), actions(m))
POMDPs.states(m::PMDP) = generate_states(pp(m))

"""
 --------------------- FINITE HORIZON -----------------------------
"""
function generate_stage_states(pp::PMDPProblem, t::Timestep)::AbstractArray{<:State}
    c_it = Iterators.product([0:cᵣ for cᵣ in pp.c₀]...)
    s_it = Iterators.product(c_it, 1:(n_products(pp)+1)) # +1 for empty_product
    states = [State(SVector(args[1]...), t, args[2]) for args in s_it]
end

function stage_stateindices(pp::PMDPProblem, t::Int64)::LinearIndices
    C_sizes = pp.c₀ .+ 1                # +1 for 0 capacity
    prd_sizes = n_products(pp)+1        # +1 for empty product

    LinearIndices((C_sizes..., prd_sizes))
end

function FiniteHorizonPOMDPs.stage_states(mdp::PMDP, epoch::Int64)::Array{State}
    return generate_stage_states(pp(mdp), epoch)
end

function FiniteHorizonPOMDPs.stage_stateindex(mdp::PMDP, s::State, epoch::Int64)
    i = findfirst(sp -> sp.c==s.c && sp.iₚ==s.iₚ, generate_stage_states(pp(mdp), epoch))
    stage_stateindices(pp(mdp), epoch)[i]
    # findfirst(isequal(s), generate_states(pp(mdp), epoch))
end

function FiniteHorizonPOMDPs.stage_stateindex(mdp::PMDP, s::State)
    FiniteHorizonPOMDPs.stage_stateindex(mdp, s, FiniteHorizonPOMDPs.stage(s))
end

FiniteHorizonPOMDPs.stage(s::State)= s.t
FiniteHorizonPOMDPs.HorizonLength(::Type{<:PMDP}) = FiniteHorizon()
FiniteHorizonPOMDPs.horizon(mdp::PMDP) = selling_period_end(mdp)


text:
# Data for Robust Optimization
# Version: 1.0
# Date: April 7th, 2019
# 1. Data Import -------------------------------------------------------------------------------------------------------
file = openxl("data.xlsx")
vec_timeProdDev = readxl(file, "timeProdDev!B2:B11")
vec_costInvest = readxl(file, "costInvest!B2:B5")
vec_costProd = readxl(file, "costProd!B2:B11")
vec_demand = readxl(file, "demand!B2:B11")
mat_prodOnMachine = readxl(file, "prodOnMachine!B2:E11")
vec_timeAvai = readxl(file, "timeAvai!B2:B5")
vec_timeProd = readxl(file, "timeProd!B2:B11")
# 2. Data Process ------------------------------------------------------------------------------------------------------
# Function to calculate parameters
function paras_budgetMILP(num_x, num_y)
    vec_c = hcat(zeros(num_x))
    for i = 1: 4
        vec_c[(4 * i - 3): (4 * i), 1] = repeat([vec_costProd[i]], num_y)
    end
    vec_f = hcat(vec_costInvest)
    vec_b = hcat(repeat([0], 50))
    vec_b[1: 10, 1] = vec_demand
    # mat_a
    mat_a_1 = zeros(10, num_x)
    for i = 1: 10
        mat_a_1[i, (4 * i - 3): (4 * i)] = repeat([1], 4)
    end
    mat_a_2 = zeros(num_x, num_x)
    for i = 1: num_x
        mat_a_2[i, i] = -1
    end
    mat_a = vcat(mat_a_1, mat_a_2)
    # mat_b
    mat_b_1 = zeros(10, 4)
    mat_b_2 = zeros(num_x, 4)
    epsilon = 0.000001  # epsilon must be large enough.
    # ??? It seems that the epsilon can make a difference in the final result, thought it's large enough.
    for i = 1: 10
        for j = 1: 4
            mat_b_2[(4 * i - 4 + j), j] = mat_prodOnMachine[i, j] * 1 / epsilon
        end
    end
    mat_b = vcat(mat_b_1, mat_b_2)
    # mat_a_bar
    mat_a_bar = zeros(4, num_x)
    for i = 1: 10
        for j = 1: 4
            mat_a_bar[j, (4 * i - 4 + j)] = vec_timeProd[i]
        end
    end
    mat_a_hat = zeros(4, num_x)
    for i = 1: 10
        for j = 1: 4
            mat_a_hat[j, (4 * i - 4 + j)] = vec_timeProdDev[i]
        end
    end
    mat_b_bar = zeros(4, 4)
    for i = 1: 4
        mat_b_bar[i, i] = - vec_timeAvai[i]
    end
    vec_b_bar = hcat(zeros(4))
    #
    return (vec_c, vec_f, vec_b, mat_a, mat_b, mat_a_bar, mat_a_hat, mat_b_bar, vec_b_bar)
end

function paras_stochasticLP(num_x, num_y, penalty)
    (vec_c, vec_f, vec_b, mat_a, mat_b, mat_a_bar, mat_a_hat, mat_b_bar, vec_b_bar) = paras_budgetMILP(num_x, num_y)
    #
    vec_g = hcat(penalty * ones(10, 1))
    mat_d_1 = zeros(10, 10)
    mat_d_1[diagind(mat_d_1)] .= 1
    mat_d_2 = zeros(num_x, 10)
    mat_d = vcat(mat_d_1, mat_d_2)
    mat_d_bar = zeros(4, 10)
    return (vec_c, vec_f, vec_b, mat_a, mat_b, mat_a_bar, mat_a_hat, mat_b_bar, vec_b_bar, vec_g, mat_d, mat_d_bar)
end


text:
module POLO

using Libdl

export
    ProxGradient,
    Execution,
    Utility,
    Boosting,
    Step,
    Smoothing,
    Prox,
    Loss,
    getf,
    getx!,
    getx,
    POLOSolvers

include("load_library.jl")
include("policy.jl")
include("boosting/boosting.jl")
include("step/step.jl")
include("smoothing/smoothing.jl")
include("prox/prox.jl")

include("loss/loss.jl")
include("utility/utility.jl")

include("proxgradient.jl")
include("execution/execution.jl")

include("solvers.jl")
include("POLOSolvers.jl")

end # module


text:
# -*- coding: utf-8 -*-
# wx_tests.jl

import Wx
using Base.Test

println("Testing: Wx")
@test Wx.WxApp()
println("done.")


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

using Markdown
using InteractiveUtils

# ╔═╡ 1de6669f-0ea3-4ba3-a8dc-823c3d80587b
using Example

# ╔═╡ 41705822-0e1d-4415-ab0a-e4bcd69a7ba0
using Colors

# ╔═╡ 6f95520c-7814-42ef-8d8d-448689f3b134
md"""
# Paquetes

Julia tiene màs de 1686 paquetes registrados, conformando una gran parte del ecosistema de Julia.

Para ver todos los paquetes, visita

https://pkg.julialang.org/

o bien

https://juliaobserver.com/

Ahora vamos a aprender a usarlos
"""

# ╔═╡ 106b3ed9-fd78-4d58-b5d1-f334227fb5bd
md"""
La primera vez que quieres usar un paquete en Julia, hay que agregarlo
"""

# ╔═╡ 7a0a379a-c671-4d5f-8f10-0353532e78a2
#Pkg.add("Example")

# ╔═╡ 5a32707a-150f-46ac-8e8c-55e7f09d73bd
md"""
Cada vez que usas Julia (empezar una nueva sesión en el REPL, abrir un notebook por primera vez, por ejemplo), tienes que cargar el paquete usando la palabra reservada `using`
"""

# ╔═╡ 0c48df5e-7758-400b-b2d3-1cf682dc7d65
md"""
En el código fuente de  `Example.jl` en

https://github.com/JuliaLang/Example.jl/blob/master/src/Example.jl

Vemos una función declarada como

```
hello(who::String) = "Hello, $who"
```

Si cargamos `Example`, debemos poder llamar `hello`
"""

# ╔═╡ 066eaf1a-e63c-49ec-9daa-5963ebea8013
hello("it's me. I was wondering if after all these years you'd like to meet.")

# ╔═╡ b8960f7d-7a16-49a5-a715-205b400d54de
md"""
Ahora vamos a jugar con el paquete de Colors
"""

# ╔═╡ d589b892-e9b4-4ad4-9b31-4038574ee1ca
#Pkg.add("Colors")

# ╔═╡ 8eb3fa0c-d505-4da6-920f-267291f3f71f
md"""
Creemos una bandeja de 100 colores
"""

# ╔═╡ eed87d62-4aee-4ce8-81e4-98690b4ac26f
bandeja = distinguishable_colors(100)

# ╔═╡ 6b5d2e71-7be3-466a-af58-e7a7bc705af5
md"""
y podemos crear una matriz colorida aleatoriamente con rand
"""

# ╔═╡ d7690f46-9e9d-4298-a585-025df0544942
rand(bandeja, 3, 3)

# ╔═╡ be413aad-d1af-461c-b258-5ba644012cb0
md"""
En el próximo notebook, vamos a usar un nuevo paquete para graficar datos
"""

# ╔═╡ a7036073-ce03-4b90-848c-dd9a06563bf6
md"""
### Ejercicios

7.1 Usa el paquete de  (código fuente en https://github.com/JuliaMath/Primes.jl) para encontrar el número primer más grande menor a 1,000,000
"""

# ╔═╡ d95c6285-bb5f-4951-ae57-6ab846ee30fe

# ╔═╡ Cell order:
# ╟─6f95520c-7814-42ef-8d8d-448689f3b134
# ╟─106b3ed9-fd78-4d58-b5d1-f334227fb5bd
# ╠═7a0a379a-c671-4d5f-8f10-0353532e78a2
# ╟─5a32707a-150f-46ac-8e8c-55e7f09d73bd
# ╠═1de6669f-0ea3-4ba3-a8dc-823c3d80587b
# ╟─0c48df5e-7758-400b-b2d3-1cf682dc7d65
# ╠═066eaf1a-e63c-49ec-9daa-5963ebea8013
# ╟─b8960f7d-7a16-49a5-a715-205b400d54de
# ╠═d589b892-e9b4-4ad4-9b31-4038574ee1ca
# ╠═41705822-0e1d-4415-ab0a-e4bcd69a7ba0
# ╟─8eb3fa0c-d505-4da6-920f-267291f3f71f
# ╠═eed87d62-4aee-4ce8-81e4-98690b4ac26f
# ╟─6b5d2e71-7be3-466a-af58-e7a7bc705af5
# ╠═d7690f46-9e9d-4298-a585-025df0544942
# ╟─be413aad-d1af-461c-b258-5ba644012cb0
# ╟─a7036073-ce03-4b90-848c-dd9a06563bf6
# ╠═d95c6285-bb5f-4951-ae57-6ab846ee30fe

max_stars_repo_name: miguelraz/JuliaTutorials

max_issues_repo_name: miguelraz/JuliaTutorials

max_forks_repo_name: miguelraz/JuliaTutorials


text:
module OnedWrapper

using JavaCall

const AbstractRegion = @jimport org.hipparchus.geometry.partitioning.AbstractRegion
const AbstractSubHyperplane = @jimport org.hipparchus.geometry.partitioning.AbstractSubHyperplane
const BSPTree = @jimport org.hipparchus.geometry.partitioning.BSPTree
const BoundaryProjection = @jimport org.hipparchus.geometry.partitioning.BoundaryProjection
const Class = @jimport java.lang.Class
const Collection = @jimport java.util.Collection
const Consumer = @jimport java.util.function.Consumer
const Euclidean1D = @jimport org.hipparchus.geometry.euclidean.oned.Euclidean1D
const FieldPosition = @jimport java.text.FieldPosition
const Hyperplane = @jimport org.hipparchus.geometry.partitioning.Hyperplane
const Interval = @jimport org.hipparchus.geometry.euclidean.oned.Interval
const IntervalsSet = @jimport org.hipparchus.geometry.euclidean.oned.IntervalsSet
const Iterable = @jimport java.lang.Iterable
const JIterator = @jimport java.util.Iterator
const JString = @jimport java.lang.String
const JVector = @jimport org.hipparchus.geometry.Vector
const List = @jimport java.util.List
const Locale = @jimport java.util.Locale
const NumberFormat = @jimport java.text.NumberFormat
const Object = @jimport java.lang.Object
const OrientedPoint = @jimport org.hipparchus.geometry.euclidean.oned.OrientedPoint
const ParsePosition = @jimport java.text.ParsePosition
const Point = @jimport org.hipparchus.geometry.Point
const Region = @jimport org.hipparchus.geometry.partitioning.Region
const Region_Location = @jimport org.hipparchus.geometry.partitioning.Region$Location
const Space = @jimport org.hipparchus.geometry.Space
const Spliterator = @jimport java.util.Spliterator
const StringBuffer = @jimport java.lang.StringBuffer
const SubHyperplane = @jimport org.hipparchus.geometry.partitioning.SubHyperplane
const SubHyperplane_SplitSubHyperplane = @jimport org.hipparchus.geometry.partitioning.SubHyperplane$SplitSubHyperplane
const SubOrientedPoint = @jimport org.hipparchus.geometry.euclidean.oned.SubOrientedPoint
const Transform = @jimport org.hipparchus.geometry.partitioning.Transform
const Vector1D = @jimport org.hipparchus.geometry.euclidean.oned.Vector1D
const Vector1DFormat = @jimport org.hipparchus.geometry.euclidean.oned.Vector1DFormat
const VectorFormat = @jimport org.hipparchus.geometry.VectorFormat

export Euclidean1D
export Interval
export IntervalsSet
export OrientedPoint
export SubOrientedPoint
export Vector1D
export Vector1DFormat
export add
export apply_transform
export as_list
export build_new
export check_point
export contains
export copy_self
export distance
export distance1
export distance_inf
export distance_sq
export dot_product
export empty_hyperplane
export equals
export for_each
export format
export get_available_locales
export get_barycenter
export get_boundary_size
export get_class
export get_dimension
export get_format
export get_hyperplane
export get_inf
export get_instance
export get_location
export get_norm
export get_norm1
export get_norm_inf
export get_norm_sq
export get_offset
export get_prefix
export get_remaining_region
export get_separator
export get_size
export get_space
export get_sub_space
export get_suffix
export get_sup
export get_tolerance
export get_tree
export get_vector1d_format
export get_x
export get_zero
export hash_code
export intersection
export is_direct
export is_empty
export is_full
export is_infinite
export is_na_n
export iterator
export negate
export normalize
export notify
export notify_all
export parse
export project
export project_to_boundary
export reunite
export revert_self
export same_orientation_as
export scalar_multiply
export split
export spliterator
export subtract
export to_string
export wait
export whole_hyperplane
export whole_space

include("euclidean1_d.jl")
include("interval.jl")
include("intervals_set.jl")
include("oriented_point.jl")
include("sub_oriented_point.jl")
include("vector1_d.jl")
include("vector1_d_format.jl")

end


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

"""
    create_api_cache(api_caching_behavior, api_id, ttl, type)
    create_api_cache(api_caching_behavior, api_id, ttl, type, params::Dict{String,<:Any})

Creates a cache for the GraphQL API.

# Arguments
- `api_caching_behavior`: Caching behavior.    FULL_REQUEST_CACHING: All requests are fully
  cached.    PER_RESOLVER_CACHING: Individual resolvers that you specify are cached.
- `api_id`: The GraphQL API Id.
- `ttl`: TTL in seconds for cache entries. Valid values are between 1 and 3600 seconds.
- `type`: The cache instance type. Valid values are     SMALL     MEDIUM     LARGE
  XLARGE     LARGE_2X     LARGE_4X     LARGE_8X (not available in all regions)    LARGE_12X
   Historically, instance types were identified by an EC2-style value. As of July 2020, this
  is deprecated, and the generic identifiers above should be used. The following legacy
  instance types are available, but their use is discouraged:    T2_SMALL: A t2.small
  instance type.    T2_MEDIUM: A t2.medium instance type.    R4_LARGE: A r4.large instance
  type.    R4_XLARGE: A r4.xlarge instance type.    R4_2XLARGE: A r4.2xlarge instance type.
   R4_4XLARGE: A r4.4xlarge instance type.    R4_8XLARGE: A r4.8xlarge instance type.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"atRestEncryptionEnabled"`: At rest encryption flag for cache. This setting cannot be
  updated after creation.
- `"transitEncryptionEnabled"`: Transit encryption flag when connecting to cache. This
  setting cannot be updated after creation.
"""
create_api_cache(apiCachingBehavior, apiId, ttl, type; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/ApiCaches", Dict{String, Any}("apiCachingBehavior"=>apiCachingBehavior, "ttl"=>ttl, "type"=>type); aws_config=aws_config)
create_api_cache(apiCachingBehavior, apiId, ttl, type, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/ApiCaches", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("apiCachingBehavior"=>apiCachingBehavior, "ttl"=>ttl, "type"=>type), params)); aws_config=aws_config)

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

Creates a unique key that you can distribute to clients who are executing your API.

# Arguments
- `api_id`: The ID for your GraphQL API.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: A description of the purpose of the API key.
- `"expires"`: The time from creation time after which the API key expires. The date is
  represented as seconds since the epoch, rounded down to the nearest hour. The default value
  for this parameter is 7 days from creation time. For more information, see .
"""
create_api_key(apiId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/apikeys"; aws_config=aws_config)
create_api_key(apiId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/apikeys", params; aws_config=aws_config)

"""
    create_data_source(api_id, name, type)
    create_data_source(api_id, name, type, params::Dict{String,<:Any})

Creates a DataSource object.

# Arguments
- `api_id`: The API ID for the GraphQL API for the DataSource.
- `name`: A user-supplied name for the DataSource.
- `type`: The type of the DataSource.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: A description of the DataSource.
- `"dynamodbConfig"`: Amazon DynamoDB settings.
- `"elasticsearchConfig"`: Amazon Elasticsearch Service settings.
- `"httpConfig"`: HTTP endpoint settings.
- `"lambdaConfig"`: AWS Lambda settings.
- `"relationalDatabaseConfig"`: Relational database settings.
- `"serviceRoleArn"`: The AWS IAM service role ARN for the data source. The system assumes
  this role when accessing the data source.
"""
create_data_source(apiId, name, type; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/datasources", Dict{String, Any}("name"=>name, "type"=>type); aws_config=aws_config)
create_data_source(apiId, name, type, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/datasources", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name, "type"=>type), params)); aws_config=aws_config)

"""
    create_function(api_id, data_source_name, function_version, name)
    create_function(api_id, data_source_name, function_version, name, params::Dict{String,<:Any})

Creates a Function object. A function is a reusable entity. Multiple functions can be used
to compose the resolver logic.

# Arguments
- `api_id`: The GraphQL API ID.
- `data_source_name`: The Function DataSource name.
- `function_version`: The version of the request mapping template. Currently the supported
  value is 2018-05-29.
- `name`: The Function name. The function name does not have to be unique.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The Function description.
- `"requestMappingTemplate"`: The Function request mapping template. Functions support only
  the 2018-05-29 version of the request mapping template.
- `"responseMappingTemplate"`: The Function response mapping template.
- `"syncConfig"`:
"""
create_function(apiId, dataSourceName, functionVersion, name; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/functions", Dict{String, Any}("dataSourceName"=>dataSourceName, "functionVersion"=>functionVersion, "name"=>name); aws_config=aws_config)
create_function(apiId, dataSourceName, functionVersion, name, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/functions", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("dataSourceName"=>dataSourceName, "functionVersion"=>functionVersion, "name"=>name), params)); aws_config=aws_config)

"""
    create_graphql_api(authentication_type, name)
    create_graphql_api(authentication_type, name, params::Dict{String,<:Any})

Creates a GraphqlApi object.

# Arguments
- `authentication_type`: The authentication type: API key, AWS IAM, OIDC, or Amazon Cognito
  user pools.
- `name`: A user-supplied name for the GraphqlApi.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"additionalAuthenticationProviders"`: A list of additional authentication providers for
  the GraphqlApi API.
- `"logConfig"`: The Amazon CloudWatch Logs configuration.
- `"openIDConnectConfig"`: The OpenID Connect configuration.
- `"tags"`: A TagMap object.
- `"userPoolConfig"`: The Amazon Cognito user pool configuration.
- `"xrayEnabled"`: A flag indicating whether to enable X-Ray tracing for the GraphqlApi.
"""
create_graphql_api(authenticationType, name; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis", Dict{String, Any}("authenticationType"=>authenticationType, "name"=>name); aws_config=aws_config)
create_graphql_api(authenticationType, name, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("authenticationType"=>authenticationType, "name"=>name), params)); aws_config=aws_config)

"""
    create_resolver(api_id, field_name, type_name)
    create_resolver(api_id, field_name, type_name, params::Dict{String,<:Any})

Creates a Resolver object. A resolver converts incoming requests into a format that a data
source can understand and converts the data source's responses into GraphQL.

# Arguments
- `api_id`: The ID for the GraphQL API for which the resolver is being created.
- `field_name`: The name of the field to attach the resolver to.
- `type_name`: The name of the Type.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"cachingConfig"`: The caching configuration for the resolver.
- `"dataSourceName"`: The name of the data source for which the resolver is being created.
- `"kind"`: The resolver type.    UNIT: A UNIT resolver type. A UNIT resolver is the
  default resolver type. A UNIT resolver enables you to execute a GraphQL query against a
  single data source.    PIPELINE: A PIPELINE resolver type. A PIPELINE resolver enables you
  to execute a series of Function in a serial manner. You can use a pipeline resolver to
  execute a GraphQL query against multiple data sources.
- `"pipelineConfig"`: The PipelineConfig.
- `"requestMappingTemplate"`: The mapping template to be used for requests. A resolver uses
  a request mapping template to convert a GraphQL expression into a format that a data source
  can understand. Mapping templates are written in Apache Velocity Template Language (VTL).
  VTL request mapping templates are optional when using a Lambda data source. For all other
  data sources, VTL request and response mapping templates are required.
- `"responseMappingTemplate"`: The mapping template to be used for responses from the data
  source.
- `"syncConfig"`: The SyncConfig for a resolver attached to a versioned datasource.
"""
create_resolver(apiId, fieldName, typeName; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)/resolvers", Dict{String, Any}("fieldName"=>fieldName); aws_config=aws_config)
create_resolver(apiId, fieldName, typeName, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)/resolvers", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("fieldName"=>fieldName), params)); aws_config=aws_config)

"""
    create_type(api_id, definition, format)
    create_type(api_id, definition, format, params::Dict{String,<:Any})

Creates a Type object.

# Arguments
- `api_id`: The API ID.
- `definition`: The type definition, in GraphQL Schema Definition Language (SDL) format.
  For more information, see the GraphQL SDL documentation.
- `format`: The type format: SDL or JSON.

"""
create_type(apiId, definition, format; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types", Dict{String, Any}("definition"=>definition, "format"=>format); aws_config=aws_config)
create_type(apiId, definition, format, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("definition"=>definition, "format"=>format), params)); aws_config=aws_config)

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

Deletes an ApiCache object.

# Arguments
- `api_id`: The API ID.

"""
delete_api_cache(apiId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/ApiCaches"; aws_config=aws_config)
delete_api_cache(apiId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/ApiCaches", params; aws_config=aws_config)

"""
    delete_api_key(api_id, id)
    delete_api_key(api_id, id, params::Dict{String,<:Any})

Deletes an API key.

# Arguments
- `api_id`: The API ID.
- `id`: The ID for the API key.

"""
delete_api_key(apiId, id; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/apikeys/$(id)"; aws_config=aws_config)
delete_api_key(apiId, id, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/apikeys/$(id)", params; aws_config=aws_config)

"""
    delete_data_source(api_id, name)
    delete_data_source(api_id, name, params::Dict{String,<:Any})

Deletes a DataSource object.

# Arguments
- `api_id`: The API ID.
- `name`: The name of the data source.

"""
delete_data_source(apiId, name; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/datasources/$(name)"; aws_config=aws_config)
delete_data_source(apiId, name, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/datasources/$(name)", params; aws_config=aws_config)

"""
    delete_function(api_id, function_id)
    delete_function(api_id, function_id, params::Dict{String,<:Any})

Deletes a Function.

# Arguments
- `api_id`: The GraphQL API ID.
- `function_id`: The Function ID.

"""
delete_function(apiId, functionId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/functions/$(functionId)"; aws_config=aws_config)
delete_function(apiId, functionId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/functions/$(functionId)", params; aws_config=aws_config)

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

Deletes a GraphqlApi object.

# Arguments
- `api_id`: The API ID.

"""
delete_graphql_api(apiId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)"; aws_config=aws_config)
delete_graphql_api(apiId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)", params; aws_config=aws_config)

"""
    delete_resolver(api_id, field_name, type_name)
    delete_resolver(api_id, field_name, type_name, params::Dict{String,<:Any})

Deletes a Resolver object.

# Arguments
- `api_id`: The API ID.
- `field_name`: The resolver field name.
- `type_name`: The name of the resolver type.

"""
delete_resolver(apiId, fieldName, typeName; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)"; aws_config=aws_config)
delete_resolver(apiId, fieldName, typeName, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)", params; aws_config=aws_config)

"""
    delete_type(api_id, type_name)
    delete_type(api_id, type_name, params::Dict{String,<:Any})

Deletes a Type object.

# Arguments
- `api_id`: The API ID.
- `type_name`: The type name.

"""
delete_type(apiId, typeName; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/types/$(typeName)"; aws_config=aws_config)
delete_type(apiId, typeName, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/types/$(typeName)", params; aws_config=aws_config)

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

Flushes an ApiCache object.

# Arguments
- `api_id`: The API ID.

"""
flush_api_cache(apiId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/FlushCache"; aws_config=aws_config)
flush_api_cache(apiId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/apis/$(apiId)/FlushCache", params; aws_config=aws_config)

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

Retrieves an ApiCache object.

# Arguments
- `api_id`: The API ID.

"""
get_api_cache(apiId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/ApiCaches"; aws_config=aws_config)
get_api_cache(apiId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/ApiCaches", params; aws_config=aws_config)

"""
    get_data_source(api_id, name)
    get_data_source(api_id, name, params::Dict{String,<:Any})

Retrieves a DataSource object.

# Arguments
- `api_id`: The API ID.
- `name`: The name of the data source.

"""
get_data_source(apiId, name; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/datasources/$(name)"; aws_config=aws_config)
get_data_source(apiId, name, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/datasources/$(name)", params; aws_config=aws_config)

"""
    get_function(api_id, function_id)
    get_function(api_id, function_id, params::Dict{String,<:Any})

Get a Function.

# Arguments
- `api_id`: The GraphQL API ID.
- `function_id`: The Function ID.

"""
get_function(apiId, functionId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions/$(functionId)"; aws_config=aws_config)
get_function(apiId, functionId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions/$(functionId)", params; aws_config=aws_config)

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

Retrieves a GraphqlApi object.

# Arguments
- `api_id`: The API ID for the GraphQL API.

"""
get_graphql_api(apiId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)"; aws_config=aws_config)
get_graphql_api(apiId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)", params; aws_config=aws_config)

"""
    get_introspection_schema(api_id, format)
    get_introspection_schema(api_id, format, params::Dict{String,<:Any})

Retrieves the introspection schema for a GraphQL API.

# Arguments
- `api_id`: The API ID.
- `format`: The schema format: SDL or JSON.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"includeDirectives"`: A flag that specifies whether the schema introspection should
  contain directives.
"""
get_introspection_schema(apiId, format; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/schema", Dict{String, Any}("format"=>format); aws_config=aws_config)
get_introspection_schema(apiId, format, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/schema", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("format"=>format), params)); aws_config=aws_config)

"""
    get_resolver(api_id, field_name, type_name)
    get_resolver(api_id, field_name, type_name, params::Dict{String,<:Any})

Retrieves a Resolver object.

# Arguments
- `api_id`: The API ID.
- `field_name`: The resolver field name.
- `type_name`: The resolver type name.

"""
get_resolver(apiId, fieldName, typeName; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)"; aws_config=aws_config)
get_resolver(apiId, fieldName, typeName, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)", params; aws_config=aws_config)

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

Retrieves the current status of a schema creation operation.

# Arguments
- `api_id`: The API ID.

"""
get_schema_creation_status(apiId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/schemacreation"; aws_config=aws_config)
get_schema_creation_status(apiId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/schemacreation", params; aws_config=aws_config)

"""
    get_type(api_id, format, type_name)
    get_type(api_id, format, type_name, params::Dict{String,<:Any})

Retrieves a Type object.

# Arguments
- `api_id`: The API ID.
- `format`: The type format: SDL or JSON.
- `type_name`: The type name.

"""
get_type(apiId, format, typeName; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)", Dict{String, Any}("format"=>format); aws_config=aws_config)
get_type(apiId, format, typeName, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("format"=>format), params)); aws_config=aws_config)

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

Lists the API keys for a given API.  API keys are deleted automatically 60 days after they
expire. However, they may still be included in the response until they have actually been
deleted. You can safely call DeleteApiKey to manually delete a key before it's
automatically deleted.

# Arguments
- `api_id`: The API ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results you want the request to return.
- `"nextToken"`: An identifier that was returned from the previous call to this operation,
  which can be used to return the next set of items in the list.
"""
list_api_keys(apiId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/apikeys"; aws_config=aws_config)
list_api_keys(apiId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/apikeys", params; aws_config=aws_config)

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

Lists the data sources for a given API.

# Arguments
- `api_id`: The API ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results you want the request to return.
- `"nextToken"`: An identifier that was returned from the previous call to this operation,
  which can be used to return the next set of items in the list.
"""
list_data_sources(apiId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/datasources"; aws_config=aws_config)
list_data_sources(apiId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/datasources", params; aws_config=aws_config)

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

List multiple functions.

# Arguments
- `api_id`: The GraphQL API ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results you want the request to return.
- `"nextToken"`: An identifier that was returned from the previous call to this operation,
  which can be used to return the next set of items in the list.
"""
list_functions(apiId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions"; aws_config=aws_config)
list_functions(apiId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions", params; aws_config=aws_config)

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

Lists your GraphQL APIs.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results you want the request to return.
- `"nextToken"`: An identifier that was returned from the previous call to this operation,
  which can be used to return the next set of items in the list.
"""
list_graphql_apis(; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis"; aws_config=aws_config)
list_graphql_apis(params::AbstractDict{String, Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis", params; aws_config=aws_config)

"""
    list_resolvers(api_id, type_name)
    list_resolvers(api_id, type_name, params::Dict{String,<:Any})

Lists the resolvers for a given API and type.

# Arguments
- `api_id`: The API ID.
- `type_name`: The type name.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results you want the request to return.
- `"nextToken"`: An identifier that was returned from the previous call to this operation,
  which can be used to return the next set of items in the list.
"""
list_resolvers(apiId, typeName; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)/resolvers"; aws_config=aws_config)
list_resolvers(apiId, typeName, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types/$(typeName)/resolvers", params; aws_config=aws_config)

"""
    list_resolvers_by_function(api_id, function_id)
    list_resolvers_by_function(api_id, function_id, params::Dict{String,<:Any})

List the resolvers that are associated with a specific function.

# Arguments
- `api_id`: The API ID.
- `function_id`: The Function ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results you want the request to return.
- `"nextToken"`: An identifier that was returned from the previous call to this operation,
  which you can use to return the next set of items in the list.
"""
list_resolvers_by_function(apiId, functionId; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions/$(functionId)/resolvers"; aws_config=aws_config)
list_resolvers_by_function(apiId, functionId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/functions/$(functionId)/resolvers", params; aws_config=aws_config)

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

Lists the tags for a resource.

# Arguments
- `resource_arn`: The GraphqlApi ARN.

"""
list_tags_for_resource(resourceArn; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/tags/$(resourceArn)"; aws_config=aws_config)
list_tags_for_resource(resourceArn, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/tags/$(resourceArn)", params; aws_config=aws_config)

"""
    list_types(api_id, format)
    list_types(api_id, format, params::Dict{String,<:Any})

Lists the types for a given API.

# Arguments
- `api_id`: The API ID.
- `format`: The type format: SDL or JSON.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results you want the request to return.
- `"nextToken"`: An identifier that was returned from the previous call to this operation,
  which can be used to return the next set of items in the list.
"""
list_types(apiId, format; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types", Dict{String, Any}("format"=>format); aws_config=aws_config)
list_types(apiId, format, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("GET", "/v1/apis/$(apiId)/types", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("format"=>format), params)); aws_config=aws_config)

"""
    start_schema_creation(api_id, definition)
    start_schema_creation(api_id, definition, params::Dict{String,<:Any})

Adds a new schema to your GraphQL API. This operation is asynchronous. Use to determine
when it has completed.

# Arguments
- `api_id`: The API ID.
- `definition`: The schema definition, in GraphQL schema language format.

"""
start_schema_creation(apiId, definition; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/schemacreation", Dict{String, Any}("definition"=>definition); aws_config=aws_config)
start_schema_creation(apiId, definition, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/schemacreation", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("definition"=>definition), params)); aws_config=aws_config)

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

Tags a resource with user-supplied tags.

# Arguments
- `resource_arn`: The GraphqlApi ARN.
- `tags`: A TagMap object.

"""
tag_resource(resourceArn, tags; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/tags/$(resourceArn)", Dict{String, Any}("tags"=>tags); aws_config=aws_config)
tag_resource(resourceArn, tags, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/tags/$(resourceArn)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("tags"=>tags), params)); aws_config=aws_config)

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

Untags a resource.

# Arguments
- `resource_arn`: The GraphqlApi ARN.
- `tag_keys`: A list of TagKey objects.

"""
untag_resource(resourceArn, tagKeys; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/tags/$(resourceArn)", Dict{String, Any}("tagKeys"=>tagKeys); aws_config=aws_config)
untag_resource(resourceArn, tagKeys, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("DELETE", "/v1/tags/$(resourceArn)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("tagKeys"=>tagKeys), params)); aws_config=aws_config)

"""
    update_api_cache(api_caching_behavior, api_id, ttl, type)
    update_api_cache(api_caching_behavior, api_id, ttl, type, params::Dict{String,<:Any})

Updates the cache for the GraphQL API.

# Arguments
- `api_caching_behavior`: Caching behavior.    FULL_REQUEST_CACHING: All requests are fully
  cached.    PER_RESOLVER_CACHING: Individual resolvers that you specify are cached.
- `api_id`: The GraphQL API Id.
- `ttl`: TTL in seconds for cache entries. Valid values are between 1 and 3600 seconds.
- `type`: The cache instance type. Valid values are     SMALL     MEDIUM     LARGE
  XLARGE     LARGE_2X     LARGE_4X     LARGE_8X (not available in all regions)    LARGE_12X
   Historically, instance types were identified by an EC2-style value. As of July 2020, this
  is deprecated, and the generic identifiers above should be used. The following legacy
  instance types are available, but their use is discouraged:    T2_SMALL: A t2.small
  instance type.    T2_MEDIUM: A t2.medium instance type.    R4_LARGE: A r4.large instance
  type.    R4_XLARGE: A r4.xlarge instance type.    R4_2XLARGE: A r4.2xlarge instance type.
   R4_4XLARGE: A r4.4xlarge instance type.    R4_8XLARGE: A r4.8xlarge instance type.

"""
update_api_cache(apiCachingBehavior, apiId, ttl, type; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/ApiCaches/update", Dict{String, Any}("apiCachingBehavior"=>apiCachingBehavior, "ttl"=>ttl, "type"=>type); aws_config=aws_config)
update_api_cache(apiCachingBehavior, apiId, ttl, type, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/ApiCaches/update", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("apiCachingBehavior"=>apiCachingBehavior, "ttl"=>ttl, "type"=>type), params)); aws_config=aws_config)

"""
    update_api_key(api_id, id)
    update_api_key(api_id, id, params::Dict{String,<:Any})

Updates an API key. The key can be updated while it is not deleted.

# Arguments
- `api_id`: The ID for the GraphQL API.
- `id`: The API key ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: A description of the purpose of the API key.
- `"expires"`: The time from update time after which the API key expires. The date is
  represented as seconds since the epoch. For more information, see .
"""
update_api_key(apiId, id; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/apikeys/$(id)"; aws_config=aws_config)
update_api_key(apiId, id, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/apikeys/$(id)", params; aws_config=aws_config)

"""
    update_data_source(api_id, name, type)
    update_data_source(api_id, name, type, params::Dict{String,<:Any})

Updates a DataSource object.

# Arguments
- `api_id`: The API ID.
- `name`: The new name for the data source.
- `type`: The new data source type.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The new description for the data source.
- `"dynamodbConfig"`: The new Amazon DynamoDB configuration.
- `"elasticsearchConfig"`: The new Elasticsearch Service configuration.
- `"httpConfig"`: The new HTTP endpoint configuration.
- `"lambdaConfig"`: The new AWS Lambda configuration.
- `"relationalDatabaseConfig"`: The new relational database configuration.
- `"serviceRoleArn"`: The new service role ARN for the data source.
"""
update_data_source(apiId, name, type; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/datasources/$(name)", Dict{String, Any}("type"=>type); aws_config=aws_config)
update_data_source(apiId, name, type, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/datasources/$(name)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("type"=>type), params)); aws_config=aws_config)

"""
    update_function(api_id, data_source_name, function_id, function_version, name)
    update_function(api_id, data_source_name, function_id, function_version, name, params::Dict{String,<:Any})

Updates a Function object.

# Arguments
- `api_id`: The GraphQL API ID.
- `data_source_name`: The Function DataSource name.
- `function_id`: The function ID.
- `function_version`: The version of the request mapping template. Currently the supported
  value is 2018-05-29.
- `name`: The Function name.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The Function description.
- `"requestMappingTemplate"`: The Function request mapping template. Functions support only
  the 2018-05-29 version of the request mapping template.
- `"responseMappingTemplate"`: The Function request mapping template.
- `"syncConfig"`:
"""
update_function(apiId, dataSourceName, functionId, functionVersion, name; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/functions/$(functionId)", Dict{String, Any}("dataSourceName"=>dataSourceName, "functionVersion"=>functionVersion, "name"=>name); aws_config=aws_config)
update_function(apiId, dataSourceName, functionId, functionVersion, name, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/functions/$(functionId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("dataSourceName"=>dataSourceName, "functionVersion"=>functionVersion, "name"=>name), params)); aws_config=aws_config)

"""
    update_graphql_api(api_id, name)
    update_graphql_api(api_id, name, params::Dict{String,<:Any})

Updates a GraphqlApi object.

# Arguments
- `api_id`: The API ID.
- `name`: The new name for the GraphqlApi object.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"additionalAuthenticationProviders"`: A list of additional authentication providers for
  the GraphqlApi API.
- `"authenticationType"`: The new authentication type for the GraphqlApi object.
- `"logConfig"`: The Amazon CloudWatch Logs configuration for the GraphqlApi object.
- `"openIDConnectConfig"`: The OpenID Connect configuration for the GraphqlApi object.
- `"userPoolConfig"`: The new Amazon Cognito user pool configuration for the GraphqlApi
  object.
- `"xrayEnabled"`: A flag indicating whether to enable X-Ray tracing for the GraphqlApi.
"""
update_graphql_api(apiId, name; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)", Dict{String, Any}("name"=>name); aws_config=aws_config)
update_graphql_api(apiId, name, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), params)); aws_config=aws_config)

"""
    update_resolver(api_id, field_name, type_name)
    update_resolver(api_id, field_name, type_name, params::Dict{String,<:Any})

Updates a Resolver object.

# Arguments
- `api_id`: The API ID.
- `field_name`: The new field name.
- `type_name`: The new type name.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"cachingConfig"`: The caching configuration for the resolver.
- `"dataSourceName"`: The new data source name.
- `"kind"`: The resolver type.    UNIT: A UNIT resolver type. A UNIT resolver is the
  default resolver type. A UNIT resolver enables you to execute a GraphQL query against a
  single data source.    PIPELINE: A PIPELINE resolver type. A PIPELINE resolver enables you
  to execute a series of Function in a serial manner. You can use a pipeline resolver to
  execute a GraphQL query against multiple data sources.
- `"pipelineConfig"`: The PipelineConfig.
- `"requestMappingTemplate"`: The new request mapping template. A resolver uses a request
  mapping template to convert a GraphQL expression into a format that a data source can
  understand. Mapping templates are written in Apache Velocity Template Language (VTL). VTL
  request mapping templates are optional when using a Lambda data source. For all other data
  sources, VTL request and response mapping templates are required.
- `"responseMappingTemplate"`: The new response mapping template.
- `"syncConfig"`: The SyncConfig for a resolver attached to a versioned datasource.
"""
update_resolver(apiId, fieldName, typeName; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)"; aws_config=aws_config)
update_resolver(apiId, fieldName, typeName, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)/resolvers/$(fieldName)", params; aws_config=aws_config)

"""
    update_type(api_id, format, type_name)
    update_type(api_id, format, type_name, params::Dict{String,<:Any})

Updates a Type object.

# Arguments
- `api_id`: The API ID.
- `format`: The new type format: SDL or JSON.
- `type_name`: The new type name.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"definition"`: The new definition.
"""
update_type(apiId, format, typeName; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)", Dict{String, Any}("format"=>format); aws_config=aws_config)
update_type(apiId, format, typeName, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = appsync("POST", "/v1/apis/$(apiId)/types/$(typeName)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("format"=>format), params)); aws_config=aws_config)


text:
# Note that this script can accept some limited command-line arguments, run
# `julia build_tarballs.jl --help` to see a usage message.
using BinaryBuilder
using Pkg

name = "LCIO_Julia_Wrapper"
version = v"0.10.0"

# Collection of sources required to build LCIOWrapBuilder
sources = [
	GitSource("https://github.com/jstrube/LCIO_Julia_Wrapper.git", "06ff63906b116cc9486ec3f3740e29aa4c5c8f70")
]

# Bash recipe for building across all platforms
script = raw"""
cd ${WORKSPACE}/srcdir/LCIO_Julia_Wrapper/
mkdir build && cd build
cmake -DJulia_PREFIX=${prefix} -DCMAKE_INSTALL_PREFIX=${prefix} -DCMAKE_FIND_ROOT_PATH=${libdir}/cmake -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TARGET_TOOLCHAIN} -DCMAKE_BUILD_TYPE=Release ..
make -j${nproc}
make install
install_license $WORKSPACE/srcdir/LCIO_Julia_Wrapper/LICENSE
"""

# These are the platforms we will build for by default, unless further
# platforms are passed in on the command line
platforms = Platform[
    Linux(:x86_64; libc=:glibc, compiler_abi=CompilerABI(cxxstring_abi=:cxx11)),
    MacOS(:x86_64; compiler_abi=CompilerABI(cxxstring_abi=:cxx11))
]

# The products that we will ensure are always built
products = [
    LibraryProduct("liblciowrap", :lciowrap)
]

# Dependencies that must be installed before this package can be built
dependencies = [
        Dependency(PackageSpec(name="libcxxwrap_julia_jll",version=v"0.8")),
        Dependency(PackageSpec(name="LCIO_jll", version=v"2.14.1")),
        BuildDependency(PackageSpec(name="Julia_jll",version=v"1.4.1"))
]

build_tarballs(ARGS, name, version, sources, script, platforms, products, dependencies; preferred_gcc_version=v"7")

max_stars_repo_name: kalmarek/Yggdrasil

max_issues_repo_name: kalmarek/Yggdrasil

max_forks_repo_name: kalmarek/Yggdrasil


text:
sock = UDPSocket()
bind(sock, ip"127.0.0.1", 8080)
open("output.log", "w") do f
    while true
        info("Receiving data...")
        s = String(recv(sock))
        info(s)
        write(f, s)
    end
end
close(sock)


text:
using Pkg
Pkg.add("Weave")
Pkg.add("GR")
Pkg.add("PyPlot")
Pkg.add("FFMPEG")


text:
# Autogenerated wrapper script for HYPRE_jll for aarch64-linux-musl
export libHYPRE

using OpenBLAS_jll
using LAPACK_jll
using MPICH_jll
using MicrosoftMPI_jll
JLLWrappers.@generate_wrapper_header("HYPRE")
JLLWrappers.@declare_library_product(libHYPRE, "libHYPRE.so")
function __init__()
    JLLWrappers.@generate_init_header(OpenBLAS_jll, LAPACK_jll, MPICH_jll, MicrosoftMPI_jll)
    JLLWrappers.@init_library_product(
        libHYPRE,
        "lib/libHYPRE.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()