text:
using BhAbs_Solver

using GLMakie
using HDF5
using Colors

#Slice observer from filename
function slices_observer(fname::String)

    #set_my_glmakie_theme()

    #Max iteration
    tmin ,  tmax  , max_iter = get_time_variables(fname)

    #Read Variables
    fid         = h5open( fname , "r")

    xmin = read_attribute(fid, "xmin")
    xmax = read_attribute(fid, "xmax")
    Nx   = read_attribute(fid, "xnodes")

    ymin = read_attribute(fid, "ymin")
    ymax = read_attribute(fid, "ymax")
    Ny   = read_attribute(fid, "ynodes")

    #Window dimensions and margin
    ww = 1800
    hh = 900
    fq = 0.8

    #Create Figure
    fig = Figure( resolution = (ww, hh), font  = "Helvetica")

    #Heatmap
    ax_heat = fig[2,1] = Axis(fig  , width = Fixed(fq*3/4*(ww/2)) , height = Fixed(fq*3/4*hh) )

    #Slices of plots
    ax_top = fig[1,1] = Axis(fig  , width = Fixed(fq*3/4*(ww/2)) , height = Fixed(fq*1/4*hh) )
    ax_rgt = fig[2,2] = Axis(fig  , width = Fixed(fq*1/4*(ww/2)) , height = Fixed(fq*3/4*hh) )

    #Sliders
    slider1 = Slider( fig[1,3][1,1] , range = 0:1:max_iter  , height = fq/12*hh , width = fq*(ww/2))
    slider2 = Slider( fig[1,3][2,1] , range = 1:1:Nx        , height = fq/12*hh , width = fq*(ww/2))
    slider3 = Slider( fig[1,3][3,1] , range = 1:1:Ny        , height = fq/12*hh , width = fq*(ww/2))

    #Energy plot
    ax_ene = fig[2,3] = Axis(fig  , width = Fixed(fq*(ww/2)) , height = Fixed(fq*3/4*hh) , yscale = log10)

    #Link axes
    linkyaxes!(ax_heat, ax_rgt)
    linkxaxes!(ax_heat, ax_top)

    #Get x and y coordinates
    _ , x , y , _ , _ = get_fields( fname , 1)

    #Fields and time
    ψ  = @lift(  get_fields( fname , $(slider1.value) )[4] )
    t  = @lift(  [get_fields( fname , $(slider1.value) )[1]] )

    #Slices of fields
    ψ_x_slice = @lift( ($ψ)[$(slider3.value),:]  )
    ψ_y_slice = @lift( ($ψ)[:,$(slider2.value)]  )

    #Current slide coordinate
    x_coord   = @lift(  [x[$(slider3.value)]]   )
    y_coord   = @lift(  [y[$(slider2.value)]]   )

    #Plot Energy
    a , b = get_field_energy(fname , 50 , tmax)

    #Plot field
    heatmap!(ax_heat , x , y ,ψ ,colorrange=(-3,3) , colormap = :vik  )

    #Slice indicators (lines)
    vlines!(ax_heat , x_coord  )
    hlines!(ax_heat , y_coord  )

    #Slice plot
    lines!( ax_top , x , ψ_y_slice)
    lines!( ax_rgt , ψ_x_slice , y)

    #Plot absorbing regions if dissipation is on
    diss =  read_attribute(fid, "Dissipation")
    println(Symbol(diss))
    alpha = 1.0f0
    Rorbit = 0.0
    Ω = 0.0
    R1 = 0.0
    R2 = 0-0

    if( diss == "true")
        alpha = 0.75f0
        Rorbit      = read_attribute(fid, "Rorbit")
        Ω           = read_attribute(fid, "Omega")
        R1          = read_attribute(fid, "R1")
        R2          = read_attribute(fid, "R2")
    end

println(Rorbit)
println(Ω)
println("aa")

    Rcavity  = read_attribute(fid, "R_boundary")

    #Circles
    c1 = lift(slider1.value) do v
        Circle( Point2f0( Rorbit * cos( Ω * get_fields( fname , v[] )[1] ) ,  Rorbit * sin( Ω * get_fields( fname , v[] )[1] )) , R1 )
    end

    c2 = lift(slider1.value) do v
        Circle( Point2f0( -Rorbit * cos( Ω * get_fields( fname , v[] )[1] ) ,  -Rorbit * sin( Ω * get_fields( fname , v[] )[1] )) , R2 )
    end

println("aa")
    #Plot Black Holes (aka circles)
    poly!( ax_heat , c1 , color = RGBA{Float32}(0.0f0, 0.0f0 , 0.0f0 , alpha)   )
    poly!( ax_heat , c2 , color = RGBA{Float32}(0.0f0, 0.0f0 , 0.0f0 , alpha)   )

println("bb")
   limits!(ax_top , xmin  , xmax ,   -5   ,   5   )    #Do heatmap
   limits!(ax_rgt ,   -5    ,    5   , ymin , ymax)    #Do heatmap

    poly!( ax_heat , Circle( Point2f0(0. ,  0.) , Rcavity ) , color = RGBA{Float32}(0.0f0, 0.0f0 , 0.0f0 , 0.0f0) , strokecolor = :black,  strokewidth =  1.0  )

    println("cc")
    #Plot energy
    #lines!(ax_ene , a , b/b[1])
    println("dd")

    #Time indicator
    #limits!(ax_ene , 0  , tmax ,   1E-5   ,   1E2   )    #Do heatmap
    #vlines!(ax_ene , t )
    println("ff")

    ax_ene.xlabel = "Time"
    ax_ene.ylabel = "Energy Density [ ϵ(t) / ϵ(0) ]"

    fig

end


text:
using Test
using SafeTestsets

@safetestset "bin_adder" begin include("bin_adder.jl") end
@safetestset "constructor" begin include("constructor.jl") end
@safetestset "xor" begin include("xor.jl") end

ext: jl


text:
#find how many different letters appear
#in all the persons from a group
#here that is each string separated by space
function find_yes(group_ans)

   #split string by spaces
   #string is coming with "" in the front, and it gets caught in the split
   person_ans = split(group_ans, " ")

   #find shortest string
   ans_l = [length(i) for i in person_ans if i!=""]
   shortest_string = findmin(ans_l)
   shortest_index = shortest_string[2] + 1 #correct index due to "" being counted as element
   shortest_ans = person_ans[shortest_index]

   n_words = length(person_ans)
   occur_in_all = 0

   #see how many times  the shortest string letters occur in
   #the group answers, if it occurs as many times as the number
   #of total words, then it appears in all words
   for letter in shortest_ans
      rx = Regex(string(letter))
      m = eachmatch(rx,group_ans)
      ocurrences = size(collect(m))[1]
      if ocurrences == n_words - 1 #correct because n_words counts "" as an element
         occur_in_all += 1
      end
   end

   return occur_in_all
end

f = open("input_day6","r")

temp_s = ""
sum_y = 0

#note that I modified my inputs to have an empty line at the end
for lines in readlines(f)
   #if not empty line concatenate de string with space
   if lines != ""
      global temp_s = temp_s*" "*lines
   else
      #println(temp_s)
      n = find_yes(temp_s)
      global sum_y += n
      global temp_s = ""

   end
end

println(sum_y)


text:
function checkit(loads::Vector{Float64}, oldloads::Vector{Float64}, tol::Float64)
  neq = length(loads)
  converged = true
  big = 0.0
  for i in 1:neq
    loads[i] > big && (big = abs(loads[i]))
  end
  for i in 1:neq
    abs(loads[i] - oldloads[i])/big > tol && (converged = false)
  end
  converged
end


text:
include("interpolation_cubicspline.jl")
include("interpolation_linear.jl")
include("../grids/schemes.jl")

"""
    Interpolation(x, y, gridargs...; method::Symbol = :linear, kwargs...)

Create an interpolation scheme from a set of `x` values and `y` values (to be interpolated).
`method` sets the interpolation type, and `extrapolation_bc` sets the extrapolation
boundary condition (either a valid `BoundaryCondition` or `NaN`).
"""
function create_interp_scheme(x, y, grid::InterpolationGrid; method::Symbol = :linear,
        extrapolation_bc::Union{BoundaryCondition, Float64} = Flat())
    if method == :linear
        intp = InterpolationScheme1D(grid, linear_interpolation(x, y;
            extrapolation_bc = extrapolation_bc))
    end

    return intp
end

"""
    interpolate_nans(grid, x, intp::Linear, extr::BoundaryCondition)

Interpolate `x` (which potentially has `NaN` values) linearly over the
provided `grid`.

If there are `NaN`s at the edges of `x`, then the `extrapolation_bc`
boundary condition is applied (see `Interpolations.BoundaryCondition`
documentation for more details). The boundary condition defaults to `NaN`,
which leaves the `NaN` values at the edges of `x` non-interpolated.
Other boundary conditions, like `Flat(gt)` or `Line(gt)`, with
`gt = OnCell()` or `gt = OnGrid()` will also work.
"""
function interpolate_nans(grid, x, intp::Linear,
        extrapolation_bc::Union{Interpolations.BoundaryCondition, Real} = NaN)
    idxs_nonnans = findall(.!(isnan.(x)))

    ext = LinearInterpolation(grid[idxs_nonnans], x[idxs_nonnans], extrapolation_bc = extrapolation_bc)
    ext(grid)
end

export create_interp_scheme, interpolate_nans


text:
export iauLtpb
"""
Long-term precession matrix, including ICRS frame bias.

This function is part of the International Astronomical Union's
SOFA (Standards of Fundamental Astronomy) software collection.

Status:  support function.

Given:
   epj     double         Julian epoch (TT)

Returned:
   rpb     double[3][3]   precession-bias matrix, J2000.0 to date

Notes:

   1. The matrix is in the sense

      P_date = rpb x P_ICRS,

   where P_ICRS is a vector in the Geocentric Celestial Reference
   System, and P_date is the vector with respect to the Celestial
   Intermediate Reference System at that date but with nutation
   neglected.

   2. A first order frame bias formulation is used, of sub-
   microarcsecond accuracy compared with a full 3D rotation.

   3. The Vondrak et al. (2011, 2012) 400 millennia precession model
   agrees with the IAU 2006 precession at J2000.0 and stays within
   100 microarcseconds during the 20th and 21st centuries.  It is
   accurate to a few arcseconds throughout the historical period,
   worsening to a few tenths of a degree at the end of the
   +/- 200,000 year time span.

References:

   Vondrak, J., Capitaine, N. and Wallace, P., 2011, New precession
   expressions, valid for long time intervals, Astron.Astrophys. 534,
   A22

   Vondrak, J., Capitaine, N. and Wallace, P., 2012, New precession
   expressions, valid for long time intervals (Corrigendum),
   Astron.Astrophys. 541, C1

This revision:  2015 December 6

SOFA release 2018-01-30

Copyright (C) 2018 IAU SOFA Board.  See notes at end.
"""

# void iauLtpb(double epj, double rpb[3][3])
function iauLtpb(epj::Real)
   rpb = zeros(Float64, 3, 3)

   ccall((:iauLtpb, libsofa_c), Cvoid,
         (Cdouble, Ref{Cdouble}),
          convert(Float64, epj),
          rpb)

   return SMatrix{3,3}(rpb')
end


text:
"""
The codes in this file test the correlation of the simulated 2 traits.
It seems that there is a constant positive correlation of the 2 traits.
This made it unfair for the selection of the 2 traits.
As this is like to select one, the other trait is automatically selected.
"""
cc = zeros(1000)

function qc(n)
    nqtl = [n, n]
    qtl = sim_QTL(base, nqtl...)
    qa = qtl_gt(base[:hap], qtl[1].pos)
    qb = qtl_gt(base[:hap], qtl[2].pos)
    aa = qa'qtl[1].effect
    ab = qb'qtl[2].effect
    cc = cor(aa, ab)
    println(cc)
    cc
end

for n in 100:100:1000
    for i in 1:1000
        c = qc(n)
        cc[i] = c
    end
    histogram(cc, bins=19, label="$n QTL")
    savefig("$n.pdf")
end

#=
for these 10 pdf figures:

```bash
sudo dnf install texlive-pdfjam # if necessary
pdfjam {100..1000..100}.pdf --nup 5x2 --landscape -o p.pdf
evince p.pdf
```
=#


text:
# DESCRIBING NETWORK TOPOLOGY

@doc """
Make a function that filters out strings matching the hostname of process 1.\n
""" ->
function makefiltermaster()
    #master_node = strip(remotecall_fetch(readall, 1, `hostname`), '\n')
    master_node = strip(reap(1, :(gethostname()))[1], '\n')
    function filtermaster(x)
        x != master_node
    end
    filtermaster
end

function describepids(pids; filterfn=(x)->true)

    # facts about the machines the processes run on
    #machines = [strip(remotecall_fetch(readall, w, `hostname`), '\n') for w in pids] #doesn't work on 0.4
    machines = map(p->strip(reap(p, :(gethostname()))[p], '\n'), pids)
    machine_names = sort!(collect(Set(machines)))
    machine_names = filter(filterfn, machine_names)
    num_machines = length(machine_names)

    # nominate a representative process for each machine, and define who it represents
    representative = zeros(Int64, num_machines)
    constituency = Dict()
    for (i,name) in enumerate(machine_names)
        constituency[i] = Int64[]
        for (j,machine) in enumerate(machines)
            if name==machine
                push!(constituency[i], pids[j])
                representative[i] = pids[j]
            end
        end
    end

    # assemble the groups of processes keyed by their representatives
    topo = Dict{Int64, Array{Int64, 1}}()
    for (i,p) in enumerate(representative)
        c = sort(constituency[i])
        topo[c[1]] = c
    end

    topo
end

@doc """
Return information about the resources (pids) available to us grouped by the machine they are running on.\n
keyword argument: remote=0 (default) specifies remote machines; remote=1 the local machine; remote=2 all machines.\n
length(topo) gives the number of unique nodes.\n
keys(topo) gives the id of a single process on each compute node.\n
values(topo) gives the ids of all processes running on each compute node.
""" ->
function describepids(; remote=0)
    pids = procs()
    if remote==0
        filterfn = makefiltermaster()
    elseif remote==1
        filtertrue = makefiltermaster()
        filterfn = (x)->!filtertrue(x)
    elseif remote==2
        filterfn=(x)->true
    end
    describepids(pids; filterfn=filterfn)
end

function localpids()
    topo = describepids(remote=1)
    topo[collect(keys(topo))[1]]
end

@doc """
For splitting work evenly across computers.
""" ->
function preferredorder(topology)
    arrtop = reduce(hcat, values(topology))
    arrrow = [arrtop[i,:]' for i in 1:size(arrtop)[1]]
    vec(reduce(vcat, arrrow))
end

function invtopology(topology)
    myrep = Dict()
    for rep in keys(topology)
        for pid in topology[rep]
            myrep[pid] = rep
        end
    end
    return myrep
end

# CHUNKING OF ARRAYS

function chunkit(axlen::Int, ncomps::Int)

    chunksz = map(Int64, zeros(ncomps))

    for i in 1:axlen
        chunksz[i%ncomps + 1] += 1
    end

    chunknd = cumsum(chunksz)
    chunkst = vcat(0, chunknd[1:end-1]) + 1

    [chunkst[i]:chunknd[i] for i in 1:ncomps]
end

function broadcast_shared(topo, elty_, value, symb)

    # CONFIG INFO
    reps_ = collect(keys(topo))

    # SHAPE
    T,V = size(value)

    # CREATE ON A SINGLE PROCESS ON EACH NODE
    remote_refs = sow(reps, symb, :( copy!(SharedArray($elty_, ($T, $V), pids=[$topo[myid()]]), $value) ));

    # MAKE ARRAY ACCESSIBLE ON ALL OTHER PROCS ON NODE
    @sync for r in reps_
        @async begin
        sow(topo[r], symb, :(fetch($remote_refs[$r])));
        end
    end
end


text:
Base.length(s::Symbol) = 1

"Turns a vector into single column
v = [1,2,[3,2,[3,4,5,6,1,1,1,11,1]]]
plainvector(v)'
1  2  3  4  5  6  11
The boolean unq specifies if the output will be filtered to return a vector of unique values
"
function plainvector(_v,unq=true)

	v = copy(_v)
	for i=1:length(v)
		if typeof(v[i])!=Int
			bucket = collect(v[i])
			deleteat!(v,i)

			v=vcat(v,plainvector(bucket,unq))
		end
	end

	for i=1:length(v)
		if typeof(v[i])  != Int
			v[i] = v[i][1]
		end
	end

	unq? unique(v) : v
end

function get_productionid(prod::Union{Symbol,Array{Any,1}})
	if typeof(prod) == Symbol
		p = eval(prod)
		return p[2]
	else
		return prod[2]
	end
end

function get_productions(id::Union{Int,Symbol,Array{Any,1}})
	tp = typeof(id)
	if tp == Int
		return productions[id]
	elseif tp == Symbol
		return eval(id)[1]
	elseif tp == Array{Any,1}
		return id[1]
	end
end

function convertGrammar(g=grammar)
	output_prof = ""
	output_code = ""
	prof_file = open("grammar_prof.txt","w+")
	code_file = open("grammar_code.txt","w+")
	for p in grammar
		line = prodToString(p)
		output_code = output_code*line

		buff_prof = replace(line,"|   .","| epsilon")
		buff_prof = replace(buff_prof,". ","")
		buff_prof = replace(buff_prof,"->","=")
		buff_prof = replace(buff_prof,"  "," ")
		output_prof = output_prof*buff_prof*"\n"

	end
	f = open("../especificações/gramática.txt","w+")
	write(f,output_prof)
	flush(f)
	close(f)

	f = open("grammar","w+")
	write(f,output_code)
	flush(f)
	close(f)
end

max_stars_repo_name: NaelsonDouglas/namelesscompiler

max_issues_repo_name: NaelsonDouglas/namelesscompiler

max_forks_repo_name: NaelsonDouglas/namelesscompiler


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

struct RouteFiltersApi <: SwaggerApi
    client::Swagger.Client
end

"""

Creates or updates a route filter in a specified resource group.
Param: resourceGroupName::String (required)
Param: routeFilterName::String (required)
Param: routeFilterParameters::RouteFilter (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: RouteFilter
"""
function _swaggerinternal_routeFiltersCreateOrUpdate(_api::RouteFiltersApi, resourceGroupName::String, routeFilterName::String, routeFilterParameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", RouteFilter, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/routeFilters/{routeFilterName}", ["azure_auth"], routeFilterParameters)
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "routeFilterName", routeFilterName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function routeFiltersCreateOrUpdate(_api::RouteFiltersApi, resourceGroupName::String, routeFilterName::String, routeFilterParameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersCreateOrUpdate(_api, resourceGroupName, routeFilterName, routeFilterParameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function routeFiltersCreateOrUpdate(_api::RouteFiltersApi, response_stream::Channel, resourceGroupName::String, routeFilterName::String, routeFilterParameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersCreateOrUpdate(_api, resourceGroupName, routeFilterName, routeFilterParameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Deletes the specified route filter.
Param: resourceGroupName::String (required)
Param: routeFilterName::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: Nothing
"""
function _swaggerinternal_routeFiltersDelete(_api::RouteFiltersApi, resourceGroupName::String, routeFilterName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/routeFilters/{routeFilterName}", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "routeFilterName", routeFilterName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function routeFiltersDelete(_api::RouteFiltersApi, resourceGroupName::String, routeFilterName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersDelete(_api, resourceGroupName, routeFilterName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function routeFiltersDelete(_api::RouteFiltersApi, response_stream::Channel, resourceGroupName::String, routeFilterName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersDelete(_api, resourceGroupName, routeFilterName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Gets the specified route filter.
Param: resourceGroupName::String (required)
Param: routeFilterName::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Param: expand::String
Return: RouteFilter
"""
function _swaggerinternal_routeFiltersGet(_api::RouteFiltersApi, resourceGroupName::String, routeFilterName::String, api_version::String, subscriptionId::String; expand=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", RouteFilter, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/routeFilters/{routeFilterName}", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "routeFilterName", routeFilterName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_param(_ctx.query, "\$expand", expand)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function routeFiltersGet(_api::RouteFiltersApi, resourceGroupName::String, routeFilterName::String, api_version::String, subscriptionId::String; expand=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersGet(_api, resourceGroupName, routeFilterName, api_version, subscriptionId; expand=expand, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function routeFiltersGet(_api::RouteFiltersApi, response_stream::Channel, resourceGroupName::String, routeFilterName::String, api_version::String, subscriptionId::String; expand=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersGet(_api, resourceGroupName, routeFilterName, api_version, subscriptionId; expand=expand, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Gets all route filters in a subscription.
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: RouteFilterListResult
"""
function _swaggerinternal_routeFiltersList(_api::RouteFiltersApi, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", RouteFilterListResult, "/subscriptions/{subscriptionId}/providers/Microsoft.Network/routeFilters", ["azure_auth"])
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function routeFiltersList(_api::RouteFiltersApi, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersList(_api, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function routeFiltersList(_api::RouteFiltersApi, response_stream::Channel, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersList(_api, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Gets all route filters in a resource group.
Param: resourceGroupName::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: RouteFilterListResult
"""
function _swaggerinternal_routeFiltersListByResourceGroup(_api::RouteFiltersApi, resourceGroupName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", RouteFilterListResult, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/routeFilters", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function routeFiltersListByResourceGroup(_api::RouteFiltersApi, resourceGroupName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersListByResourceGroup(_api, resourceGroupName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function routeFiltersListByResourceGroup(_api::RouteFiltersApi, response_stream::Channel, resourceGroupName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersListByResourceGroup(_api, resourceGroupName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Updates tags of a route filter.
Param: resourceGroupName::String (required)
Param: routeFilterName::String (required)
Param: parameters::TagsObject (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: RouteFilter
"""
function _swaggerinternal_routeFiltersUpdateTags(_api::RouteFiltersApi, resourceGroupName::String, routeFilterName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", RouteFilter, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/routeFilters/{routeFilterName}", ["azure_auth"], parameters)
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "routeFilterName", routeFilterName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function routeFiltersUpdateTags(_api::RouteFiltersApi, resourceGroupName::String, routeFilterName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersUpdateTags(_api, resourceGroupName, routeFilterName, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function routeFiltersUpdateTags(_api::RouteFiltersApi, response_stream::Channel, resourceGroupName::String, routeFilterName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_routeFiltersUpdateTags(_api, resourceGroupName, routeFilterName, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

export routeFiltersCreateOrUpdate, routeFiltersDelete, routeFiltersGet, routeFiltersList, routeFiltersListByResourceGroup, routeFiltersUpdateTags


text:
module HammerScalpel

using Distributed, SharedArrays
using NLopt, FiniteDifferences, GridInterpolations
using JLD2, Plots

export solveModel, nopolicy, withpolicy, createFig5, createFig6, createFig7

include("solveModel.jl")
include("nopolicy.jl")
include("withpolicy.jl")
include("withpolicy_parallel.jl")
include("helperfunctions.jl")
include("figures_paper.jl")

end


text:
@cache struct Vern6Cache{uType,rateType,uNoUnitsType,TabType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  k1::rateType
  k2::rateType
  k3::rateType
  k4::rateType
  k5::rateType
  k6::rateType
  k7::rateType
  k8::rateType
  k9::rateType
  utilde::uType
  tmp::uType
  rtmp::rateType
  atmp::uNoUnitsType
  tab::TabType
end

function alg_cache(alg::Vern6,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  tab = Vern6Tableau(constvalue(uBottomEltypeNoUnits),constvalue(tTypeNoUnits))
  k1 = zero(rate_prototype)
  k2 = zero(rate_prototype); k3 = k2;                   k4 = zero(rate_prototype);
  k5 = zero(rate_prototype); k6 = zero(rate_prototype); k7 = zero(rate_prototype);
  k8 = k3;                   k9 = zero(rate_prototype);
  utilde = zero(u); tmp = zero(u); atmp = similar(u,uEltypeNoUnits);
  rtmp = uEltypeNoUnits === eltype(u) ? utilde : zero(rate_prototype);
  Vern6Cache(u,uprev,k1,k2,k3,k4,k5,k6,k7,k8,k9,utilde,tmp,rtmp,atmp,tab)
end

struct Vern6ConstantCache{TabType} <: OrdinaryDiffEqConstantCache
  tab::TabType
end

function alg_cache(alg::Vern6,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  tab = Vern6Tableau(constvalue(uBottomEltypeNoUnits),constvalue(tTypeNoUnits))
  Vern6ConstantCache(tab)
end

@cache struct Vern7Cache{uType,rateType,uNoUnitsType,TabType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  k1::rateType
  k2::rateType
  k3::rateType
  k4::rateType
  k5::rateType
  k6::rateType
  k7::rateType
  k8::rateType
  k9::rateType
  k10::rateType
  utilde::uType
  tmp::uType
  rtmp::rateType
  atmp::uNoUnitsType
  tab::TabType
end

function alg_cache(alg::Vern7,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  tab = Vern7Tableau(constvalue(uBottomEltypeNoUnits),constvalue(tTypeNoUnits))
  k1 = zero(rate_prototype); k2 = zero(rate_prototype); k3 = k2                  ; k4 = zero(rate_prototype);
  k5 = zero(rate_prototype); k6 = zero(rate_prototype); k7 = zero(rate_prototype); k8 = zero(rate_prototype);
  k9 = zero(rate_prototype); k10 = k2                 ; utilde = zero(u)
  tmp = zero(u); atmp = similar(u,uEltypeNoUnits)
  rtmp = uEltypeNoUnits === eltype(u) ? utilde : zero(rate_prototype);
  Vern7Cache(u,uprev,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,utilde,tmp,rtmp,atmp,tab)
end

struct Vern7ConstantCache{TabType} <: OrdinaryDiffEqConstantCache
  tab::TabType
end

function alg_cache(alg::Vern7,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  tab = Vern7Tableau(constvalue(uBottomEltypeNoUnits),constvalue(tTypeNoUnits))
  Vern7ConstantCache(tab)
end

@cache struct Vern8Cache{uType,rateType,uNoUnitsType,TabType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  k1::rateType
  k2::rateType
  k3::rateType
  k4::rateType
  k5::rateType
  k6::rateType
  k7::rateType
  k8::rateType
  k9::rateType
  k10::rateType
  k11::rateType
  k12::rateType
  k13::rateType
  utilde::uType
  tmp::uType
  rtmp::rateType
  atmp::uNoUnitsType
  tab::TabType
end

function alg_cache(alg::Vern8,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  tab = Vern8Tableau(constvalue(uBottomEltypeNoUnits),constvalue(tTypeNoUnits))
  k1 = zero(rate_prototype); k2 = zero(rate_prototype); k3 = k2;
  k4 = zero(rate_prototype);
  k5 = k2                  ; k6 = zero(rate_prototype); k7 = zero(rate_prototype);
  k8 = zero(rate_prototype); tmp = zero(u)
  k9 = zero(rate_prototype); k10 = zero(rate_prototype); k11 = zero(rate_prototype);
  k12 = zero(rate_prototype); k13 = k4
  utilde = zero(u)
  atmp = similar(u,uEltypeNoUnits)
  rtmp = uEltypeNoUnits === eltype(u) ? utilde : zero(rate_prototype);
  Vern8Cache(u,uprev,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,k12,k13,utilde,tmp,rtmp,atmp,tab)
end

struct Vern8ConstantCache{TabType} <: OrdinaryDiffEqConstantCache
  tab::TabType
end

function alg_cache(alg::Vern8,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  tab = Vern8Tableau(constvalue(uBottomEltypeNoUnits),constvalue(tTypeNoUnits))
  Vern8ConstantCache(tab)
end

@cache struct Vern9Cache{uType,rateType,uNoUnitsType,TabType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  k1::rateType
  k2::rateType
  k3::rateType
  k4::rateType
  k5::rateType
  k6::rateType
  k7::rateType
  k8::rateType
  k9::rateType
  k10::rateType
  k11::rateType
  k12::rateType
  k13::rateType
  k14::rateType
  k15::rateType
  k16::rateType
  utilde::uType
  tmp::uType
  rtmp::rateType
  atmp::uNoUnitsType
  tab::TabType
end

function alg_cache(alg::Vern9,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{true}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  tab = Vern9Tableau(constvalue(uBottomEltypeNoUnits),constvalue(tTypeNoUnits))
  k1 = zero(rate_prototype); k2 = zero(rate_prototype);k3 = k2;
  k4 = zero(rate_prototype);
  k5 = k3;                   k6 = zero(rate_prototype);k7 = k4;
  k8 = k5;
  k9 = zero(rate_prototype); k10 = zero(rate_prototype); k11 = zero(rate_prototype);
  k12 = zero(rate_prototype);
  k13 = zero(rate_prototype); k14 = zero(rate_prototype); k15 = zero(rate_prototype);
  k16 =k6;
  utilde = zero(u); tmp = zero(u); atmp = similar(u,uEltypeNoUnits);
  rtmp = uEltypeNoUnits === eltype(u) ? utilde : zero(rate_prototype);
  Vern9Cache(u,uprev,k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,k12,k13,k14,k15,k16,utilde,tmp,rtmp,atmp,tab)
end

struct Vern9ConstantCache{TabType} <: OrdinaryDiffEqConstantCache
  tab::TabType
end

function alg_cache(alg::Vern9,u,rate_prototype,::Type{uEltypeNoUnits},::Type{uBottomEltypeNoUnits},::Type{tTypeNoUnits},uprev,uprev2,f,t,dt,reltol,p,calck,::Val{false}) where {uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits}
  tab = Vern9Tableau(constvalue(uBottomEltypeNoUnits),constvalue(tTypeNoUnits))
  Vern9ConstantCache(tab)
end


text:
# ---
# title: 763. Partition Labels
# id: problem763
# author: Tian Jun
# date: 2020-10-31
# difficulty: Medium
# categories: Two Pointers, Greedy
# link: <https://leetcode.com/problems/partition-labels/description/>
# hidden: true
# ---
#
# A string `S` of lowercase English letters is given. We want to partition this
# string into as many parts as possible so that each letter appears in at most
# one part, and return a list of integers representing the size of these parts.
#
#
#
# **Example 1:**
#
#
#
#     Input: S = "ababcbacadefegdehijhklij"
#     Output: [9,7,8]
#     Explanation:
#     The partition is "ababcbaca", "defegde", "hijhklij".
#     This is a partition so that each letter appears in at most one part.
#     A partition like "ababcbacadefegde", "hijhklij" is incorrect, because it splits S into less parts.
#
#
#
#
# **Note:**
#
#   * `S` will have length in range `[1, 500]`.
#   * `S` will consist of lowercase English letters (`'a'` to `'z'`) only.
#
#
#
#
## @lc code=start
using LeetCode

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


text:
cd(dirname(@__FILE__))
include("./functions/load_inputfunctions.jl")
J,δ =1000,.01
cs,al =  get_params()
include("./functions/load_cluster.jl")
include("./functions/load_stuff.jl")

B,S = generate_structures(cs,al,nworkers(),J,δ)

solve_Benders!(B)
println("")


text:
@enum Active Initial Final

mutable struct ActiveAggregation
    active::Active

    function ActiveAggregation()
        return new(Initial)
    end
end

function shift(gap::AbstractFloat, τ::AbstractFloat)
    return gap <= τ
end

"""
    HybridAggregation

Functor object for using hybrid aggregation in an L-shaped algorithm. Create by supplying a [`HybridAggregate`](@ref) object through `aggregate ` in the `LShapedSolver` factory function and then pass to a `StochasticPrograms.jl` model.

...
# Parameters
- `initial::AbstractAggregator`: Initial aggregation scheme
- `final::AbstractAggregator`: Final aggregation scheme
- `τ::T`: The active aggregation scheme is switched from `initial` to `final` when the optimality gap decreases below `τ`
...
"""
struct HybridAggregation{T <: AbstractFloat, Agg1 <: AbstractAggregation, Agg2 <: AbstractAggregation} <: AbstractAggregation
    initial::Agg1
    final::Agg2
    τ::T
    active::ActiveAggregation

    function HybridAggregation(initial::AbstractAggregation, final::AbstractAggregation, τ::AbstractFloat)
        Agg1 = typeof(initial)
        Agg2 = typeof(final)
        T = typeof(τ)
        return new{T,Agg1,Agg2}(initial, final, τ, ActiveAggregation())
    end
end

function active(aggregation::HybridAggregation)
    if aggregation.active.active == Initial
        return aggregation.initial
    end
    return aggregation.final
end

function activate_final!(aggregation::HybridAggregation)
    aggregation.active.active = Final
    return nothing
end

function aggregate_cut!(lshaped::AbstractLShaped, aggregation::HybridAggregation, cut::HyperPlane)
    return aggregate_cut!(lshaped, active(aggregation), cut)
end

function aggregate_cut!(cutqueue::CutQueue, aggregation::HybridAggregation, metadata::MetaData, t::Integer, cut::HyperPlane, x::AbstractArray)
    return aggregate_cut!(cutqueue, active(aggregation), metadata, t, cut, x)
end

function num_thetas(num_subproblems::Integer, aggregation::HybridAggregation)
    return num_thetas(num_subproblems, active(aggregation))
end

function num_thetas(num_subproblems::Integer, aggregation::HybridAggregation, sp::DistributedScenarioProblems)
    return num_thetas(num_subproblems, active(aggregation), sp)
end

function flush!(lshaped::AbstractLShaped, aggregation::HybridAggregation)
    added = flush!(lshaped, active(aggregation))
    if shift(gap(lshaped), aggregation.τ)
        activate_final!(aggregation)
    end
    return added
end

function flush!(cutqueue::CutQueue, aggregation::HybridAggregation, metadata::MetaData, t::Integer, x::AbstractArray) where T <: AbstractFloat
    flush!(cutqueue, active(aggregation), metadata, t, x)
    if shift(fetch(metadata, t, :gap), aggregation.τ)
        activate_final!(aggregation)
    end
    return nothing
end

# API
# ------------------------------------------------------------
"""
    HybridAggregate(initial::AbstractAggregator, final::AbstractAggregator, τ::AbstractFloat)

Factory object for [`HybridAggregation`](@ref). Pass to `aggregate ` in the `LShapedSolver` factory function. See ?HybridAggregation for parameter descriptions.

"""
mutable struct HybridAggregate <: AbstractAggregator
    initial::AbstractAggregator
    final::AbstractAggregator
    τ::Float64

    function HybridAggregate(initial::AbstractAggregator, final::AbstractAggregator, τ::AbstractFloat)
        return new(initial, final, τ)
    end
end

struct InitialAggregator <: AggregationParameter end

function MOI.get(aggregator::HybridAggregate, ::InitialAggregator)
    return aggregator.initial
end

function MOI.set(aggregator::HybridAggregate, ::InitialAggregator, initial::AbstractAggregator)
    return aggregator.initial = initial
end

struct FinalAggregator <: AggregationParameter end

function MOI.get(aggregator::HybridAggregate, ::FinalAggregator)
    return aggregator.final
end

function MOI.set(aggregator::HybridAggregate, ::FinalAggregator, final::AbstractAggregator)
    return aggregator.final = final
end

function (aggregator::HybridAggregate)(num_subproblems::Integer, T::Type{<:AbstractFloat})
    initial = aggregator.initial(num_subproblems, T)
    final = aggregator.final(num_subproblems, T)
    n₁ = num_thetas(num_subproblems, initial)
    n₂ = num_thetas(num_subproblems, final)
    n₁ == n₂|| error("Inconsistent number of theta variables in hybrid aggregation: $n₁ ≠ $n₂")
    return HybridAggregation(initial, final, convert(T, aggregator.τ))
end

function remote_aggregator(aggregation::HybridAggregation, sp::AbstractScenarioProblems, w::Integer)
    return HybridAggregate(remote_aggregator(aggregation.initial, sp, w),
                           remote_aggregator(aggregation.final, sp, w),
                           aggregation.τ)
end

function str(aggregator::HybridAggregate)
    return "hybrid aggregation consisting of $(str(aggregator.initial)) and $(str(aggregator.final))"
end


text:
using LightXML

"""
    xml2parameters!(p::Params, input_xml)

Load `p` from XML file (e.g. `.in.xml`).
"""
function xml2parameters!(p, input_xml::AbstractString, verbose=true)
  # READ INPUT XML
  params = Dict{Any, Any}()
  try
    params = xml2dict(input_xml, verbose)

  catch e
    println(e)
  end

  set_parameters(p, params)

  params
end

function xml2dict(fname::AbstractString, verbose::Bool=true)
  params = Dict{Any, Any}()
  xdoc = parse_file(fname)
  xroot = LightXML.root(xdoc)
  for c in child_nodes(xroot)
    if is_elementnode(c)
      for p in child_nodes(c)
        if is_elementnode(p)
          e = XMLElement(p)
          if LightXML.name(e) == "PARAMETER"
            verbose && println(attribute(e, "name"), " = ", content(e))
            params[attribute(e, "name")] = content(e)
          end
        end
      end
    end
  end
  return params
end

function paramset2xml(params::Dict, prefix::AbstractString)
  for (i, param_set) in enumerate(product(values(params)...))
    xdoc = XMLDocument()
    xroot = create_root(xdoc, "SIMULATION")
    pn = new_child(xroot, "PARAMETERS")
    for (k, p) in zip(keys(params), param_set)
      pc = new_child(pn, "PARAMETER")
      add_text(pc, string(p))
      set_attribute(pc, "name", string(k))
    end
    save_file(xdoc, prefix * ".task" * string(i) * ".in.xml")
  end
end

function params2xml(params::Dict, prefix::AbstractString, taskid::Int; overwrite=false, ext=".in.xml", root="")
  xdoc = XMLDocument()
  xroot = create_root(xdoc, "SIMULATION")
  pn = new_child(xroot, "PARAMETERS")
  for (k, p) in params
    pc = new_child(pn, "PARAMETER")
    add_text(pc, string(p))
    set_attribute(pc, "name", string(k))
  end
  of = joinpath(root, prefix * ".task" * string(taskid) * ext)
  (!isfile(of) || overwrite) && save_file(xdoc, of)
end

max_stars_repo_name: crstnbr/dqmc

max_issues_repo_name: crstnbr/dqmc

max_forks_repo_name: crstnbr/dqmc


text:
"""
    pretty_print
Pretty-print a buffer of expressions (and comments) to an output stream, add
blank lines at appropriate places for readability, and also apply some simple
post-editing.
"""
function pretty_print end

function pretty_print(io, node::ExprNode, options::Dict)
    # warn if the node has been edited in the codegen pass.
    # this usually happens when certain new node type is support in the codegen,
    # but the corresponding `pretty_print` method is missing.
    !isempty(node.exprs) && @warn "skip a node that has non-empty expressions. is the corresponding `pretty_print` method defined?"
    return nothing
end

function pretty_print(io, node::ExprNode{FunctionProto}, options::Dict)
    @assert !isempty(node.exprs)
    for expr in node.exprs
        println(io, expr)
        println(io)
    end
    return nothing
end

function pretty_print(io, node::ExprNode{FunctionNoProto}, options::Dict)
    @assert !isempty(node.exprs)
    file, line, col = get_file_line_column(node.cursor)
    println(io, "# no prototype is found for this function at $(basename(file)):$line:$col, please use with caution")
    for expr in node.exprs
        println(io, expr)
        println(io)
    end
    return nothing
end

function pretty_print(io, node::ExprNode{TypedefElaborated}, options::Dict)
    for expr in node.exprs
        println(io, expr)
        println(io)
    end
    return nothing
end

function pretty_print(io, node::ExprNode{TypedefMutualRef}, options::Dict)
    for expr in node.exprs
        println(io, expr)
        println(io)
    end
    return nothing
end

function pretty_print(io, node::ExprNode{TypedefFunction}, options::Dict)
    @assert length(node.exprs) == 1

    # print C code
    toks = tokenize(node.cursor)
    c_str = reduce((lhs, rhs) -> lhs * " " * rhs, [tok.text for tok in toks])
    println(io, "# " * replace(c_str, "\n" => "\n#"))

    # print expr
    println(io, node.exprs[1])
    println(io)

    return nothing
end

function pretty_print(io, node::ExprNode{TypedefToAnonymous}, options::Dict)
    @assert length(node.exprs) == 1
    println(io, node.exprs[1])
    println(io)
    return nothing
end

function pretty_print(io, node::ExprNode{TypedefDefault}, options::Dict)
    for expr in node.exprs
        println(io, expr)
        println(io)
    end
    return nothing
end

function pretty_print(io, node::ExprNode{<:AbstractStructNodeType}, options::Dict)
    @assert !isempty(node.exprs)
    for expr in node.exprs
        println(io, expr)
        println(io)
    end
    return nothing
end

function pretty_print(io, node::ExprNode{StructMutualRef}, options::Dict)
    @assert !isempty(node.exprs)
    expr = node.exprs[1]

    @assert Meta.isexpr(expr, :struct)
    mutability = expr.args[1] ? "mutable struct" : "struct"
    struct_name = expr.args[2]
    println(io, "$mutability $struct_name")

    block = expr.args[3]
    @assert Meta.isexpr(block, :block)
    for ex in block.args
        if Meta.isexpr(ex, :block)
            println(io, "    # " * string(ex.args[1]))
        else
            println(io, "    " * string(ex))
        end
    end
    println(io, "end")
    println(io)

    for expr in node.exprs[2:end]
        println(io, expr)
        println(io)
    end

    return nothing
end

function pretty_print(io, node::ExprNode{<:AbstractEnumNodeType}, options::Dict)
    @assert !isempty(node.exprs)
    use_native_enum = get(options, "use_julia_native_enum_type", false)
    enum_values = Dict()

    head = node.exprs[1]
    head_expr = head.args[3]
    if length(node.exprs) ≥ 2
        enum_macro = use_native_enum ? "@enum" : "@cenum"
        println(io, "$enum_macro $head_expr begin")
        for i = 2:length(node.exprs)
            expr = node.exprs[i]
            if use_native_enum
                n, v = expr.args
                if haskey(enum_values, v)
                    println(io, "    # " * string(expr))
                    continue
                end
                enum_values[v] = n
            end
            println(io, "    " * string(expr))
        end
        println(io, "end")
    else
        # for empty enums, we make it an alias of the corresponding integer type
        enum_name, int_ty = head_expr.args[3].args
        println(io, "const $enum_name = $int_ty")
    end
    println(io)

    return nothing
end

function pretty_print(io, node::ExprNode{<:RecordLayouts}, options::Dict)
    @assert !isempty(node.exprs)
    for expr in node.exprs
        println(io, expr)
        println(io)
    end
    return nothing
end

pretty_print(io, node::ExprNode{<:ForwardDecls}, options::Dict) = nothing

function pretty_print(io, node::ExprNode{<:OpaqueTags}, options::Dict)
    @assert length(node.exprs) == 1
    expr = node.exprs[1]

    codegen_ops = get(options, "codegen", Dict())
    opaque_as_mutable = get(codegen_ops, "opaque_as_mutable_struct", true)

    if opaque_as_mutable && Meta.isexpr(expr, :struct)
        struct_name = expr.args[2]
        println(io, "mutable struct $struct_name end")
    else
        println(io, expr)
    end
    println(io)
    return nothing
end

pretty_print(io, node::ExprNode{<:UnknownDefaults}, options::Dict) = nothing
pretty_print(io, node::ExprNode{<:DuplicatedTags}, options::Dict) = nothing

## EXPERIMENTAL
function pretty_print(io, node::ExprNode{<:AbstractMacroNodeType}, options::Dict)
    for expr in node.exprs
        if Meta.isexpr(expr, :block)
            println(io, string(expr.args[1]))
        else
            println(io, expr)
        end
        println(io)
    end
    return nothing
end


text:
using Printf

function parse_map(s)
    lines = split(s, "\n")
    map_arr = zeros(Bool, length(lines), length(lines[1]))
    for (row_idx, l) in enumerate(lines)
        for (col_idx, c) in enumerate(l)
            map_arr[row_idx, col_idx] = (c == '#')
        end
    end
    return map_arr
end

function count_trees_on_slope(map_arr, down, right)
    tree_counter = 0
    x, y = 1, 1
    n_rows, n_cols = size(map_arr)
    while x <= n_rows
        if map_arr[x, y]
            tree_counter += 1
        end
        x += down
        y = (y + right) % n_cols
        if y == 0
            y = n_cols
        end
    end
    return tree_counter
end

function run(s)
    # Your code here
    map_arr = parse_map(s)
    return count_trees_on_slope(map_arr, 1, 3)
end

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

function main()
    res, time, memory = @timed run(ARGS[1])
    println("_duration:$(time * 1000)")
    println(res)
end

main()


text:
"""
Parses requests and extracts parameters, setting up the call variables and invoking
the appropiate route handler function.
"""
module Router

import Revise
import Reexport, Logging
import HTTP, URIParser, HttpCommon, Sockets, Millboard, Dates, OrderedCollections, JSON
import Genie

include("mimetypes.jl")

export route, routes, channel, channels, serve_static_file
export GET, POST, PUT, PATCH, DELETE, OPTIONS
export tolink, linkto, responsetype, toroute
export @params, @routes, @channels

Reexport.@reexport using HttpCommon

const GET     = "GET"
const POST    = "POST"
const PUT     = "PUT"
const PATCH   = "PATCH"
const DELETE  = "DELETE"
const OPTIONS = "OPTIONS"

const BEFORE_HOOK  = :before
const AFTER_HOOK   = :after

const request_mappings = Dict{Symbol,String}(
  :text       => "text/plain",
  :html       => "text/html",
  :json       => "application/json",
  :javascript => "application/javascript",
  :form       => "application/x-www-form-urlencoded",
  :multipart  => "multipart/form-data",
  :file       => "application/octet-stream",
  :xml        => "text/xml"
)

const pre_match_hooks = Function[]
const pre_response_hooks = Function[]
const content_negotiation_hooks = Function[]

"""
    mutable struct Route

Representation of a route object
"""
mutable struct Route
  method::String
  path::String
  action::Function
  name::Union{Symbol,Nothing}
end

Route(; method = GET, path = "", action = (() -> error("Route not set")), name = nothing) = Route(method, path, action, name)

"""
    mutable struct Channel

Representation of a WebSocket Channel object
"""
mutable struct Channel
  path::String
  action::Function
  name::Union{Symbol,Nothing}

  Channel(; path = "", action = (() -> error("Channel not set")), name = nothing) =
    new(path, action)
end

function Base.show(io::IO, r::Route)
  print(io, "[$(r.method)] $(r.path) => $(r.action) | :$(r.name)")
end
function Base.show(io::IO, c::Channel)
  print(io, "[WS] $(c.path) => $(c.action) | :$(c.name)")
end

const _routes = OrderedCollections.OrderedDict{Symbol,Route}()
const _channels = OrderedCollections.OrderedDict{Symbol,Channel}()

"""
    mutable struct Params{T}

Collection of key value pairs representing the parameters of the current request - response cycle.
"""
mutable struct Params{T}
  collection::Dict{Symbol,T}
end
Params() = Params(setup_base_params())

Base.Dict(params::Params) = params.collection

Base.getindex(params, keys...) = getindex(Dict(params), keys...)

"""
    _params_()

Reference to the request variables collection.
"""
function _params_()
  task_local_storage(:__params)
end
function _params_(key::Union{String,Symbol})
  task_local_storage(:__params)[key]
end

"""
    ispayload(req::HTTP.Request)

True if the request can carry a payload - that is, it's a `POST`, `PUT`, or `PATCH` request
"""
ispayload(req::HTTP.Request) = req.method in [POST, PUT, PATCH]

"""
    route_request(req::Request, res::Response, ip::IPv4 = Genie.config.server_host) :: Response

First step in handling a request: sets up @params collection, handles query vars, negotiates content.
"""
function route_request(req::HTTP.Request, res::HTTP.Response, ip::Sockets.IPv4 = Sockets.IPv4(Genie.config.server_host)) :: HTTP.Response
  params = Params()
  params.collection[:request_ipv4] = ip

  for f in unique(content_negotiation_hooks)
    req, res, params.collection = f(req, res, params.collection)
  end

  if is_static_file(req.target)
    Genie.config.server_handle_static_files && return serve_static_file(req.target)

    return error(req.target, response_mime(), Val(404))
  end

  Genie.Configuration.isdev() && Revise.revise()

  for f in unique(pre_match_hooks)
    req, res, params.collection = f(req, res, params.collection)
  end

  res = match_routes(req, res, params)

  res.status == 404 && req.method == OPTIONS && return preflight_response()

  for f in unique(pre_response_hooks)
    req, res, params.collection = f(req, res, params.collection)
  end

  reqstatus = "$(req.target) $(res.status)\n"

  if res.status < 400
    @info reqstatus
  else
    @error reqstatus
  end

  res
end

"""
    route_ws_request(req::Request, msg::String, ws_client::HTTP.WebSockets.WebSocket, ip::IPv4 = Genie.config.server_host) :: String

First step in handling a web socket request: sets up @params collection, handles query vars.
"""
function route_ws_request(req, msg::String, ws_client, ip::Sockets.IPv4 = Sockets.IPv4(Genie.config.server_host)) :: String
  params = Params()

  params.collection[Genie.PARAMS_WS_CLIENT] = ws_client

  extract_get_params(URIParser.URI(req.target), params)

  Genie.Configuration.isdev() && Revise.revise()

  match_channels(req, msg, ws_client, params)
end

function Base.push!(collection, name::Symbol, item::Union{Route,Channel})
  collection[name] = item
end

"""
Named Genie routes constructors.
"""
function route(action::Function, path::String; method = GET, named::Union{Symbol,Nothing} = nothing) :: Route
  route(path, action, method = method, named = named)
end
function route(path::String, action::Function; method = GET, named::Union{Symbol,Nothing} = nothing) :: Route
  r = Route(method = method, path = path, action = action, name = named)

  if named === nothing
    r.name = routename(r)
  end

  Router.push!(_routes, r.name, r)
end

"""
Named Genie channels constructors.
"""
function channel(action::Function, path::String; named::Union{Symbol,Nothing} = nothing) :: Channel
  channel(path, action, named = named)
end
function channel(path::String, action::Function; named::Union{Symbol,Nothing} = nothing) :: Channel
  c = Channel(path = path, action = action, name = named)

  if named === nothing
    c.name = channelname(c)
  end

  Router.push!(_channels, c.name, c)
end

"""
    routename(params) :: Symbol

Computes the name of a route.
"""
function routename(params::Route) :: Symbol
  baptizer(params, String[lowercase(params.method)])
end

"""
    channelname(params) :: Symbol

Computes the name of a channel.
"""
function channelname(params::Channel) :: Symbol
  baptizer(params, String[])
end

"""
    baptizer(params::Union{Route,Channel}, parts::Vector{String}) :: Symbol

Generates default names for routes and channels.
"""
function baptizer(params::Union{Route,Channel}, parts::Vector{String}) :: Symbol
  for uri_part in split(params.path, "/", keepempty = false)
    startswith(uri_part, ":") && continue # we ignore named params
    push!(parts, lowercase(uri_part))
  end

  join(parts, "_") |> Symbol
end

"""
The list of the defined named routes.
"""
function named_routes() :: OrderedCollections.OrderedDict{Symbol,Route}
  _routes
end
const namedroutes = named_routes

"""
    @routes

Collection of named routes
"""
macro routes()
  _routes
end

"""
    named_channels() :: Dict{Symbol,Any}

The list of the defined named channels.
"""
function named_channels() :: OrderedCollections.OrderedDict{Symbol,Channel}
  _channels
end
const namedchannels = named_channels

"""
    @channels

Collection of named channels.
"""
macro channels()
  _channels
end

"""
Gets the `Route` correspoding to `routename`
"""
function get_route(route_name::Symbol; default::Union{Route,Nothing} = Route()) :: Route
  haskey(named_routes(), route_name) ?
    named_routes()[route_name] :
    (if default === nothing
      Base.error("Route named `$route_name` is not defined")
    else
      @warn "Route named `$route_name` is not defined"
      default
    end)
end

"""
    routes() :: Vector{Route}

Returns a vector of defined routes.
"""
function routes() :: Vector{Route}
  collect(values(_routes)) |> reverse
end

"""
    channels() :: Vector{Channel}

Returns a vector of defined channels.
"""
function channels() :: Vector{Channel}
  collect(values(_channels)) |> reverse
end

"""
    delete!(routes, route_name::Symbol)

Removes the route with the corresponding name from the routes collection and returns the collection of remaining routes.
"""
function delete!(routes::OrderedCollections.OrderedDict{Symbol,Route}, key::Symbol) :: OrderedCollections.OrderedDict{Symbol,Route}
  OrderedCollections.delete!(routes, key)
end

"""
Generates the HTTP link corresponding to `route_name` using the parameters in `d`.
"""
function to_link(route_name::Symbol, d::Dict{Symbol,T}; preserve_query::Bool = true, extra_query::Dict = Dict())::String where {T}
  route = get_route(route_name)

  result = String[]
  for part in split(route.path, "/")
    if occursin("#", part)
      part = split(part, "#")[1]
    end

    if startswith(part, ":")
      var_name = split(part, "::")[1][2:end] |> Symbol
      ( isempty(d) || ! haskey(d, var_name) ) && error("Route $route_name expects param $var_name")
      push!(result, pathify(d[var_name]))
      Base.delete!(d, var_name)
      continue
    end

    push!(result, part)
  end

  query_vars = Dict{String,String}()
  if preserve_query && haskey(task_local_storage(), :__params) && haskey(task_local_storage(:__params), :REQUEST)
    query = URIParser.URI(task_local_storage(:__params)[:REQUEST].target).query
    if ! isempty(query)
      for pair in split(query, '&')
        try
          parts = split(pair, '=')
          query_vars[parts[1]] = parts[2]
        catch ex
          # @error ex
        end
      end
    end
  end

  for (k,v) in extra_query
    query_vars[string(k)] = string(v)
  end

  qv = String[]
  for (k,v) in query_vars
    push!(qv, "$k=$v")
  end

  join(result, "/") * ( ! isempty(qv) ? "?" : "" ) * join(qv, "&")
end

"""
Generates the HTTP link corresponding to `route_name` using the parameters in `route_params`.
"""
function to_link(route_name::Symbol; preserve_query::Bool = true, extra_query::Dict = Dict(), route_params...) :: String
  to_link(route_name, route_params_to_dict(route_params), preserve_query = preserve_query, extra_query = extra_query)
end

const link_to = to_link
const linkto = link_to
const tolink = to_link
const toroute = to_link

"""
    route_params_to_dict(route_params)

Converts the route params to a `Dict`.
"""
function route_params_to_dict(route_params) :: Dict{Symbol,Any}
  Dict{Symbol,Any}(route_params)
end

"""
    action_controller_params(action::Function, params::Params) :: Nothing

Sets up the :action_controller, :action, and :controller key - value pairs of the `params` collection.
"""
function action_controller_params(action::Function, params::Params) :: Nothing
  params.collection[:action_controller] = action |> string |> Symbol
  params.collection[:action] = nameof(action)
  params.collection[:controller] = (action |> typeof).name.module |> string |> Symbol

  nothing
end

"""
    run_hook(controller::Module, hook_type::Symbol) :: Bool

Invokes the designated hook.
"""
function run_hook(controller::Module, hook_type::Symbol) :: Bool
  isdefined(controller, hook_type) || return false

  getfield(controller, hook_type) |> Base.invokelatest

  true
end

"""
    match_routes(req::Request, res::Response, params::Params) :: Response

Matches the invoked URL to the corresponding route, sets up the execution environment and invokes the controller method.
"""
function match_routes(req::HTTP.Request, res::HTTP.Response, params::Params) :: HTTP.Response
  for r in routes()
    r.method != req.method && continue

    parsed_route, param_names, param_types = parse_route(r.path)

    uri = URIParser.URI(to_uri(req.target))
    regex_route = try
      Regex("^" * parsed_route * "\$")
    catch
      @error "Invalid route $parsed_route"

      continue
    end

    occursin(regex_route, uri.path) || parsed_route == "/*" || continue

    params.collection = setup_base_params(req, res, params.collection)
    task_local_storage(:__params, params.collection)

    occursin("?", req.target) && extract_get_params(URIParser.URI(to_uri(req.target)), params)

    extract_uri_params(uri.path, regex_route, param_names, param_types, params) || continue

    ispayload(req) && extract_post_params(req, params)
    ispayload(req) && extract_request_params(req, params)
    action_controller_params(r.action, params)

    for f in unique(content_negotiation_hooks)
      req, res, params.collection = f(req, res, params.collection)
    end

    params.collection[Genie.PARAMS_ROUTE_KEY] = r

    get!(params.collection, Genie.PARAMS_MIME_KEY, MIME(request_type(req)))

    controller = (r.action |> typeof).name.module

    return  try
              run_hook(controller, BEFORE_HOOK)

              result = try
                (r.action)() |> to_response
              catch
                Base.invokelatest(r.action) |> to_response
              end

              run_hook(controller, AFTER_HOOK)

              result

            catch ex
              if isa(ex, Genie.Exceptions.ExceptionalResponse)
                return ex.response
              elseif isa(ex, Genie.Exceptions.RuntimeException)
                rethrow(ex)
              elseif isa(ex, Genie.Exceptions.InternalServerException)
                return error(ex.message, response_mime(), Val(500))
              elseif isa(ex, Genie.Exceptions.NotFoundException)
                return error(ex.resource, response_mime(), Val(404))
              elseif isa(ex, Exception)
                rethrow(ex)
              end
            end
  end

  error(req.target, response_mime(params.collection), Val(404))
end

"""
    match_channels(req::Request, msg::String, ws_client::HTTP.WebSockets.WebSocket, params::Params) :: String

Matches the invoked URL to the corresponding channel, sets up the execution environment and invokes the channel controller method.
"""
function match_channels(req, msg::String, ws_client, params::Params) :: String
  for c in channels()
    parsed_channel, param_names, param_types = parse_channel(c.path)

    payload::Dict{String,Any} = try
                                  JSON.parse(msg)
                                catch ex
                                  Dict{String,Any}()
                                end

    uri = haskey(payload, "channel") ? "/" * payload["channel"] : "/"
    uri = haskey(payload, "message") ? uri * "/" * payload["message"] : uri

    haskey(payload, "payload") && (params.collection[:payload] = payload["payload"])

    regex_channel = Regex("^" * parsed_channel * "\$")

    (! occursin(regex_channel, uri)) && continue

    params.collection = setup_base_params(req, nothing, params.collection)
    task_local_storage(:__params, params.collection)

    extract_uri_params(uri, regex_channel, param_names, param_types, params) || continue

    action_controller_params(c.action, params)

    params.collection[Genie.PARAMS_CHANNELS_KEY] = c

    controller = (c.action |> typeof).name.module

    return  try
                run_hook(controller, BEFORE_HOOK)

                result = try
                  (c.action)() |> string
                catch
                  Base.invokelatest(c.action) |> string
                end

                run_hook(controller, AFTER_HOOK)

                result
              catch ex
                isa(ex, Exception) ? sprint(showerror, ex) : rethrow(ex)
              end
  end

  string("ERROR : 404 - Not found")
end

"""
    parse_route(route::String) :: Tuple{String,Vector{String},Vector{Any}}

Parses a route and extracts its named params and types.
"""
function parse_route(route::String) :: Tuple{String,Vector{String},Vector{Any}}
  parts = String[]
  param_names = String[]
  param_types = Any[]

  if occursin('#', route) || occursin(':', route)
    validation_match = "[\\w\\-\\.\\+\\,\\s\\%]+"

    for rp in split(route, "/", keepempty = false)
      if occursin("#", rp)
        x = split(rp, "#")
        rp = x[1]
        validation_match = x[2]
      end

      if startswith(rp, ":")
        param_type =  if occursin("::", rp)
                        x = split(rp, "::")
                        rp = x[1]
                        getfield(@__MODULE__, Symbol(x[2]))
                      else
                        Any
                      end
        param_name = rp[2:end]

        rp = """(?P<$param_name>$validation_match)"""

        push!(param_names, param_name)
        push!(param_types, param_type)
      end

      push!(parts, rp)
    end
  else
    parts = split(route, "/", keepempty = false)
  end

  "/" * join(parts, "/"), param_names, param_types
end

"""
    parse_channel(channel::String) :: Tuple{String,Vector{String},Vector{Any}}

Parses a channel and extracts its named parms and types.
"""
function parse_channel(channel::String) :: Tuple{String,Vector{String},Vector{Any}}
  parts = String[]
  param_names = String[]
  param_types = Any[]

  if occursin(':', channel)
    for rp in split(channel, "/", keepempty = false)
      if startswith(rp, ":")
        param_type =  if occursin("::", rp)
                        x = split(rp, "::")
                        rp = x[1]
                        getfield(@__MODULE__, Symbol(x[2]))
                      else
                        Any
                      end
        param_name = rp[2:end]
        rp = """(?P<$param_name>[\\w\\-]+)"""
        push!(param_names, param_name)
        push!(param_types, param_type)
      end
      push!(parts, rp)
    end
  else
    parts = split(channel, "/", keepempty = false)
  end

  "/" * join(parts, "/"), param_names, param_types
end

"""
    extract_uri_params(uri::String, regex_route::Regex, param_names::Vector{String}, param_types::Vector{Any}, params::Params) :: Bool

Extracts params from request URI and sets up the `params` `Dict`.
"""
function extract_uri_params(uri::String, regex_route::Regex, param_names::Vector{String}, param_types::Vector{Any}, params::Params) :: Bool
  matches = match(regex_route, uri)

  i = 1
  for param_name in param_names
    try
      params.collection[Symbol(param_name)] = convert(param_types[i], matches[param_name])
    catch ex
      @error "Failed to match URI params between $(param_types[i])::$(typeof(param_types[i])) and $(matches[param_name])::$(typeof(matches[param_name]))"
      @error ex

      return false
    end

    i += 1
  end

  true # this must be bool cause it's used in bool context for chaining
end

"""
    extract_get_params(uri::URI, params::Params) :: Bool

Extracts query vars and adds them to the execution `params` `Dict`.
"""
function extract_get_params(uri::URIParser.URI, params::Params) :: Bool
  # GET params
  if ! isempty(uri.query)
    for query_part in split(uri.query, "&")
      qp = split(query_part, "=")
      (size(qp)[1] == 1) && (push!(qp, ""))

      k = Symbol(URIParser.unescape(qp[1]))
      v = URIParser.unescape(qp[2])
      params.collection[k] = params.collection[Genie.PARAMS_GET_KEY][k] = v
    end
  end

  true # this must be bool cause it's used in bool context for chaining
end

"""
    extract_post_params(req::Request, params::Params) :: Nothing

Parses POST variables and adds the to the `params` `Dict`.
"""
function extract_post_params(req::HTTP.Request, params::Params) :: Nothing
  ispayload(req) || return nothing

  input = Genie.Input.all(req)

  for (k, v) in input.post
    nested_keys(k, v, params)

    k = Symbol(k)
    params.collection[k] = params.collection[Genie.PARAMS_POST_KEY][k] = v
  end

  params.collection[Genie.PARAMS_FILES] = input.files

  nothing
end

"""
    extract_request_params(req::HTTP.Request, params::Params) :: Nothing

Sets up the `params` key-value pairs corresponding to a JSON payload.
"""
function extract_request_params(req::HTTP.Request, params::Params) :: Nothing
  ispayload(req) || return nothing

  params.collection[Genie.PARAMS_RAW_PAYLOAD] = String(req.body)

  if request_type_is(req, :json) && content_length(req) > 0
    try
      params.collection[Genie.PARAMS_JSON_PAYLOAD] = JSON.parse(params.collection[Genie.PARAMS_RAW_PAYLOAD])
    catch ex
      @error sprint(showerror, ex)
      @warn "Setting @params(:JSON_PAYLOAD) to Nothing"

      params.collection[Genie.PARAMS_JSON_PAYLOAD] = nothing
    end
  else
    params.collection[Genie.PARAMS_JSON_PAYLOAD] = nothing
  end

  nothing
end

"""
    content_type(req::HTTP.Request) :: String

Gets the content-type of the request.
"""
function content_type(req::HTTP.Request) :: String
  get(Genie.HTTPUtils.Dict(req), "content-type", get(Genie.HTTPUtils.Dict(req), "accept", ""))
end

"""
    content_length(req::HTTP.Request) :: Int

Gets the content-length of the request.
"""
function content_length(req::HTTP.Request) :: Int
  parse(Int, get(Genie.HTTPUtils.Dict(req), "content-length", "0"))
end
function content_length() :: Int
  content_length(_params_(Genie.PARAMS_REQUEST_KEY))
end

"""
    request_type_is(req::HTTP.Request, request_type::Symbol) :: Bool

Checks if the request content-type is of a certain type.
"""
function request_type_is(req::HTTP.Request, request_type::Symbol) :: Bool
  ! in(request_type, keys(request_mappings) |> collect) && error("Unknown request type $request_type - expected one of $(keys(request_mappings) |> collect).")

  occursin(request_mappings[request_type], content_type(req)) && return true

  false
end
function request_type_is(request_type::Symbol) :: Bool
  request_type_is(_params_(Genie.PARAMS_REQUEST_KEY), request_type)
end

"""
    request_type(req::HTTP.Request) :: Symbol

Gets the request's content type.
"""
function request_type(req::HTTP.Request) :: Symbol
  accepted_encodings = split(content_type(req), ',')

  for accepted_encoding in accepted_encodings
    for (k,v) in request_mappings
      if occursin(v, accepted_encoding)
        return k
      end
    end
  end

  Symbol(accepted_encodings[1])
end

"""
    nested_keys(k::String, v, params::Params) :: Nothing

Utility function to process nested keys and set them up in `params`.
"""
function nested_keys(k::String, v, params::Params) :: Nothing
  if occursin(".", k)
    parts = split(k, ".", limit = 2)
    nested_val_key = Symbol(parts[1])

    if haskey(params.collection, nested_val_key) && isa(params.collection[nested_val_key], Dict)
      ! haskey(params.collection[nested_val_key], Symbol(parts[2])) && (params.collection[nested_val_key][Symbol(parts[2])] = v)
    elseif ! haskey(params.collection, nested_val_key)
      params.collection[nested_val_key] = Dict()
      params.collection[nested_val_key][Symbol(parts[2])] = v
    end
  end

  nothing
end

"""
    setup_base_params(req::Request, res::Response, params::Dict{Symbol,Any}) :: Dict{Symbol,Any}

Populates `params` with default environment vars.
"""
function setup_base_params(req::HTTP.Request = HTTP.Request(), res::Union{HTTP.Response,Nothing} = req.response,
                            params::Dict{Symbol,Any} = Dict{Symbol,Any}()) :: Dict{Symbol,Any}
  params[Genie.PARAMS_REQUEST_KEY]   = req
  params[Genie.PARAMS_RESPONSE_KEY]  = res
  params[Genie.PARAMS_POST_KEY]      = Dict{Symbol,Any}()
  params[Genie.PARAMS_GET_KEY]       = Dict{Symbol,Any}()

  params[Genie.PARAMS_FILES]         = Dict{String,Genie.Input.HttpFile}()

  params
end

"""
    to_response(action_result) :: Response

Converts the result of invoking the controller action to a `Response`.
"""
to_response(action_result::HTTP.Response)::HTTP.Response = action_result
to_response(action_result::Tuple)::HTTP.Response = HTTP.Response(action_result...)
to_response(action_result::Vector)::HTTP.Response = HTTP.Response(join(action_result))
to_response(action_result::Nothing)::HTTP.Response = HTTP.Response("")
to_response(action_result::String)::HTTP.Response = HTTP.Response(action_result)
to_response(action_result::Genie.Exceptions.ExceptionalResponse)::HTTP.Response = action_result.response
to_response(action_result::Exception)::HTTP.Response = throw(action_result)
to_response(action_result::Any)::HTTP.Response = HTTP.Response(string(action_result))

"""
    @params

The object containing the request variables collection.
"""
macro params()
  quote
    task_local_storage(:__params)
  end
end
macro params(key)
  :((@params)[$key])
end
macro params(key, default)
  quote
    haskey(@params, $key) ? @params($key) : $default
  end
end

"""
    @request()

The request object.
"""
macro request()
  :(_params_(Genie.PARAMS_REQUEST_KEY))
end

"""
    response_type{T}(params::Dict{Symbol,T}) :: Symbol
    response_type(params::Params) :: Symbol

Returns the content-type of the current request-response cycle.
"""
function response_type(params::Dict{Symbol,T})::Symbol where {T}
  get(params, :response_type, request_type(params[Genie.PARAMS_REQUEST_KEY]))
end
function response_type(params::Params) :: Symbol
  response_type(params.collection)
end
function response_type() :: Symbol
  response_type(@params())
end

"""
    response_type{T}(check::Symbol, params::Dict{Symbol,T}) :: Bool

Checks if the content-type of the current request-response cycle matches `check`.
"""
function response_type(check::Symbol, params::Dict{Symbol,T})::Bool where {T}
  check == response_type(params)
end

const responsetype = response_type

"""
    append_to_routes_file(content::String) :: Nothing

Appends `content` to the app's route file.
"""
function append_to_routes_file(content::String) :: Nothing
  open(Genie.ROUTES_FILE_NAME, "a") do io
    write(io, "\n" * content)
  end

  nothing
end

"""
    is_static_file(resource::String) :: Bool

Checks if the requested resource is a static file.
"""
function is_static_file(resource::String) :: Bool
  isfile(file_path(to_uri(resource).path))
end

"""
    to_uri(resource::String) :: URI

Attempts to convert `resource` to URI
"""
function to_uri(resource::String) :: URIParser.URI
  try
    URIParser.URI(resource)
  catch ex
    qp = URIParser.query_params(resource) |> keys |> collect
    escaped_resource = join(map( x -> ( startswith(x, "/") ? escape_resource_path(string(x)) : URIParser.escape(string(x)) ) * "=" * URIParser.escape(URIParser.query_params(resource)[string(x)]), qp ), "&")

    URIParser.URI(escaped_resource)
  end
end

"""
    escape_resource_path(resource::String)

Cleans up paths to resources.
"""
function escape_resource_path(resource::String)
  startswith(resource, "/") || return resource
  resource = resource[2:end]

  "/" * join(map(x -> URIParser.escape(x), split(resource, "?")), "?")
end

"""
    serve_static_file(resource::String) :: Response

Reads the static file and returns the content as a `Response`.
"""
function serve_static_file(resource::String; root = Genie.config.server_document_root) :: HTTP.Response
  startswith(resource, "/") || (resource = "/$resource")
  resource_path = try
                    URIParser.URI(resource).path
                  catch ex
                    resource
                  end
  f = file_path(resource_path, root = root)

  if isfile(f)
    return HTTP.Response(200, file_headers(f), body = read(f, String))
  elseif isdir(f)
    isfile(joinpath(f, "index.html")) && return serve_static_file(joinpath(f, "index.html"), root = root)
    isfile(joinpath(f, "index.htm")) && return serve_static_file(joinpath(f, "index.htm"), root = root)
  else
    bundled_path = joinpath(@__DIR__, "..", "files", "static", resource[2:end])
    if isfile(bundled_path)
      return HTTP.Response(200, file_headers(bundled_path), body = read(bundled_path, String))
    end
  end

  @error "404 Not Found $f"
  error(resource, response_mime(), Val(404))
end

"""
preflight_response() :: HTTP.Response

Sets up the preflight CORS response header.
"""
function preflight_response() :: HTTP.Response
  HTTP.Response(200, Genie.config.cors_headers, body = "Success")
end

"""
    response_mime()

Returns the MIME type of the response.
"""
function response_mime(params::Dict{Symbol,Any} = _params_())
  rm = get!(params, Genie.PARAMS_MIME_KEY, request_type(params[Genie.PARAMS_REQUEST_KEY]))

  if isempty(string(rm()))
    params[Genie.PARAMS_MIME_KEY] = request_type(params[Genie.PARAMS_REQUEST_KEY])
  end

  params[Genie.PARAMS_MIME_KEY]
end

"""
    error

Not implemented function for error response.
"""
function error end

function trymime(mime::Any)
  try
    mime()
  catch _
    mime
  end
end

function error(error_message::String, mime::Any, ::Val{500}; error_info::String = "") :: HTTP.Response
  HTTP.Response(500, ["Content-Type" => string(trymime(mime))], body = "500 Internal Error - $error_message. $error_info")
end

function error(error_message::String, mime::Any, ::Val{404}; error_info::String = "") :: HTTP.Response
  HTTP.Response(404, ["Content-Type" => string(trymime(mime))], body = "404 Not Found - $error_message. $error_info")
end

function error(error_code::Int, error_message::String, mime::Any; error_info::String = "") :: HTTP.Response
  HTTP.Response(error_code, ["Content-Type" => string(trymime(mime))], body = "$error_code Error - $error_message. $error_info")
end

"""
    file_path(resource::String; within_doc_root = true) :: String

Returns the path to a resource file. If `within_doc_root` it will automatically prepend the document root to `resource`.
"""
function file_path(resource::String; within_doc_root = true, root = Genie.config.server_document_root) :: String
  within_doc_root = within_doc_root && root == Genie.config.server_document_root
  joinpath(within_doc_root ? Genie.config.server_document_root : root, resource[(startswith(resource, "/") ? 2 : 1):end])
end
const filepath = file_path

"""
    pathify(x) :: String

Returns a proper URI path from a string `x`.
"""
pathify(x) :: String = replace(string(x), " "=>"-") |> lowercase |> URIParser.escape

"""
    file_extension(f) :: String

Returns the file extesion of `f`.
"""
file_extension(f) :: String = ormatch(match(r"(?<=\.)[^\.\\/]*$", f), "")

"""
    file_headers(f) :: Dict{String,String}

Returns the file headers of `f`.
"""
function file_headers(f) :: Vector{Pair{String,String}}
  ["Content-Type" => get(mimetypes, file_extension(f), "application/octet-stream")]
end

ormatch(r::RegexMatch, x) = r.match
ormatch(r::Nothing, x) = x

end


text:
using Test, ConsoleInput

origin_stdin = stdin
test_in = open("./test.txt", "r")
redirect_stdin(test_in)

@testset "DlmType" begin
    @test isa(' ', ConsoleInput.DlmType)
    @test isa("abc", ConsoleInput.DlmType)
    @test isa(r"^\s*(?:#|$)", ConsoleInput.DlmType)

    function dlm()::String
            "false"
    end
    @test isa(dlm(), ConsoleInput.DlmType)
end

@testset "readInt" begin
    @test ConsoleInput.readInt(test_in) == 1
    @test ConsoleInput.readInt(test_in) == [1, 2, 3, 4, 5]
    @test ConsoleInput.readInt(test_in, ",") == [6, 7, 8, 9, 10]
end

@testset "readString" begin
    @test ConsoleInput.readString(test_in) == "Lorem"
    @test ConsoleInput.readString(test_in) == ["Lorem", "ipsum", "es", "simplemente"]
    @test ConsoleInput.readString(test_in, ";") == ["consectetur", "adipiscing", "elit"]
end

@testset "readGeneral" begin
    @test ConsoleInput.readGeneral(Float64, test_in) == 0.0012
    @test ConsoleInput.readGeneral(Complex{Float64}, test_in) == 0.32 + 4.5im
    @test ConsoleInput.readGeneral(Complex{Int}, test_in) == [1+5im, 10-4im, -9+8im]
end
close(test_in)
redirect_stdin(origin_stdin)


text:
using Pkg;
Pkg.activate(joinpath(@__DIR__, "..")); Pkg.instantiate()
Pkg.activate(); Pkg.instantiate()

pushfirst!(LOAD_PATH, joinpath(@__DIR__, ".."))

using Documenter, NeuralQuantum

makedocs(
    modules   = [NeuralQuantum],
    sitename  = "NeuralQuantum.jl",
    authors   = "Filippo Vicentini",
    pages     = [
            "Home"          => "index.md",
            "Manual"        => Any[
                "Basics"        => "basics.md",
                "Liouvillian"   => "liouvillian.md",
                "Networks"      => "networks.md",
                "Samplers"      => "samplers.md",
                "SR"            => "algorithms.md",
                "Optimizers"    => "optimizers.md"
            ],
            "Reference" => "reference.md"
    ],
    format    = Documenter.HTML(
                    prettyurls = haskey(ENV, "CI"),
                    mathengine = MathJax())
)

deploydocs(
    repo   = "github.com/PhilipVinc/NeuralQuantum.jl.git",
    target = "build"
    )


text:
using DrWatson
quickactivate(@__DIR__)
@show projectdir()
##
using CovidSurvey
using CSV
using DataFrames
using Dates
using StatsPlots
using Plots.PlotMeasures
using LaTeXStrings

using Random
using Turing
## ===========================================================================
# load data
# ============================================================================
fdir = projectdir("reports/parametric-model-on-2nd-wave-newdata/")
fname = "cases=2020-06-01_chains=10_hospit=true_model=parametric-cases_observ=2021-01-13_preds=CF,CC,CR,CS_sero=true_steps=2000_warmup=1000"
fname = "cases=2020-06-01_chains=10_hospit=true_model=parametric-cases_observ=2021-01-13_preds=CF,CC,CR,CS_sero=true_steps=2000_warmup=1000"
PREFIX = "RAW-"
# fname = "cases=2020-06-01_chains=10_hospit=true_model=parametric-cases_observ=2021-01-13_preds=CF,CC,CR,CS_sero=true_steps=4000_warmup=1000"
rt    = load(fdir*PREFIX*"Rt_"*fname*".csv") |> DataFrame
chain = read(fdir*PREFIX*"CHAIN_"*fname*".jls", Chains)
posterior = load(fdir*PREFIX*"GENERATED-QUANTITIES_"*fname*".bson") |> NamedTuple
data = let
    _, ps, _ = parse_savename(fname, parsetypes = (Int, Float64, Bool))
    !("preds" in keys(ps)) && (ps["preds"] = nothing)
    # ps = NamedTuple{Tuple(Symbol.(keys(ps)))}(values(ps))

    National.load_data(
          ps["observ"]
        , ps["preds"]|> CovidSurvey.parse_predictors
        , ps["cases"]
        , ps["hospit"]
        , ps["sero"]
        , iar_step = 1
        , covariates_kwargs = Dict(
            :fname => projectdir("data", "inferred_contact_rates.csv"),
            #:fname => projectdir("data", "smoothed_contact_rates.csv"), #normpath( homedir(), "data/covidsurvey/smoothed_contacts.csv" ),
            # :fname => normpath( homedir(), "data/covidsurvey/smoothed_contacts.csv" ),
            :shift => -1,
            :startdate => "2020-11-10",
            # :enddate => "2021-01-13"
        )
    )
end
# turing_data = data.turing_data;
## ===========================================================================
# plot prediction

plotlyjs()
pgfplotsx()
Plots.scalefontsizes()
Plots.scalefontsizes(2.)
p = let
    p1 = let
        i = findfirst(==(Date("2020-05-15")), data.dates)
        dates = data.dates[i:end]
        xlims   = (dates[1], dates[end])
        p = plot(; xaxis = true, xlims, ylabel="counts", legend = :outerright);
        # plot_hospit_posterior!(p, data, expected_daily_hospit)
        obs = hcat(posterior.expected_daily_cases...)[i:end,:]
        tNobs  = data.dates[data.num_observations]
        # title!(p, "posterior hospitalization counts")
        plot!(p, dates, data.cases[i:end], alpha=0.5, lc=:match, label="cases", c=:midnightblue, lw=2) #, label="Recorded daily hospitalizations (observed)"
        # vspan!(p, [DateTime("2020-11-10"), tNobs], label="fit contacts", α=0.2)
        vline!(p, [tNobs], label="end of observations", linewidth=2, lc=:black, hover="$(tNobs)")
        # vline!(p, [], label="end of observations", linewidth=2, lc=:black, ls=:dash)
        plot_confidence_timeseries!(p, dates, obs; label = "Expected daily hospitalizations")
    end

    p2 = let
        i = findfirst(==(Date("2020-05-15")), data.dates)
        dates = data.dates[i:end]
        xlims   = (dates[1], dates[end])
        p = plot(; xaxis = true, xlims, legend = :outerright, ylabel=L"R_t");
        Rt = hcat(posterior.Rt...)[i:end,:]
        tNobs  = data.dates[data.num_observations]
        # title!(p, "effective reproduction number")
        vspan!(p, [Date("2020-11-10"), tNobs], label="fit contacts", α=0.2, fc=:midnightblue)
        # vline!(p, [Date("2020-11-10")], label="fitted contacts", linewidth=2, lc=:black, ls=:dash)
        vline!(p, [tNobs], label="end of observations", linewidth=2, lc=:black, hover="$(tNobs)")
        # vline!(p, [], label="end of observations", linewidth=2, lc=:black, ls=:dash)
        plot_confidence_timeseries!(p, dates, Rt; label = "reproduction number")
    end

    plot(p1, p2, layout=(2,1), size=(800, 500), sharex=true, link=:x, legend = nothing)#xticks = tickdates
end
savefig(p, normpath(fdir,PREFIX*"FIG_hospit_"*fname*".png") )
# savefig(p, projectdir(fdir*"FIG_hospitalization_"*fname*".png") )

##

p = let#CF,CC,CR,CS
    xs = chain["α[1]"]|>vec
    p1 = histogram(xs, normalize=true, title="contacts to family", label=nothing, fc=:gray, lw=.0, xlabel="effect size", bottom_margin=5mm);
    plot!(Exponential(0.2), xlims=(0,2.0), lw=2, label="prior", legend=:topright);
    vline!([mean(xs)], lw=2, label="mean effect = $(round(mean(xs), sigdigits=2))", c=:black, ls=:dash)
    xs = chain["α[2]"]|>vec
    p2 = histogram(xs, normalize=true, title="contacts to colleagues", label=nothing, fc=:gray, lw=.0, xlabel="effect size", bottom_margin=5mm);
    plot!(Exponential(0.2), xlims=(0,2.0), lw=2, label="prior", legend=:topright);
    vline!([mean(xs)], lw=2, label="mean effect = $(round(mean(xs), sigdigits=2))", c=:black, ls=:dash)
    xs = chain["α[3]"]|>vec
    p3 = histogram(xs, normalize=true, title="contacts to friends", label=nothing, fc=:gray, lw=.0, xlabel="effect size", top_margin=5mm);
    plot!(Exponential(0.2), xlims=(0,2.0), lw=2, label="prior", legend=:topright);
    vline!([mean(xs)], lw=2, label="mean effect = $(round(mean(xs), sigdigits=2))", c=:black, ls=:dash)
    xs = chain["α[4]"]|>vec
    p4 = histogram(xs, normalize=true, title="contacts to strangers", label=nothing, fc=:gray, lw=.0, xlabel="effect size", top_margin=5mm);
    plot!(Exponential(0.2), xlims=(0,2.0), lw=2, label="prior", legend=:topright);
    vline!([mean(xs)], lw=2, label="mean effect = $(round(mean(xs), sigdigits=2))", c=:black, ls=:dash)
    plot(p1,p2,p3,p4, layout=(2,2), size=(1000, 700))
end
# savefig(p, projectdir(fdir*"FIG_hospitalization_effectsizes_"*fname*".png") )
savefig(p, normpath(fdir,PREFIX*"FIG-cases-effectsizes_"*fname*".png") )

## ============================================================================
X = data.turing_data.covariates[end,:]
i = findfirst(==(Date("2020-11-10")), rt.date)
Δrt = rt.mq[i] - rt.mq[end]
r0 = rt.mq[i]

α1 = chain["α[1]"]|>vec|>mean
α2 = chain["α[2]"]|>vec|>mean
α3 = chain["α[3]"]|>vec|>mean
α4 = chain["α[4]"]|>vec|>mean
α = [α1,α2,α3,α4]

f(r0 - α)

f = KLogistic(3.)
f⁻¹ = KLogit(3.)
f(f⁻¹(r0) + X'α) / r0
X .* α
## ==========================================================================
covariates_kwargs = Dict(
    :fname => normpath( homedir(), "data/covidsurvey/smoothed_contacts.csv" ),
    :shift => -1,
    :startdate => "2020-11-10", # >= 1000 cases / day
    # :enddate => "2021-01-13" # <= 1000 cases / day
)
covariates = National.readcovariates(; covariates_kwargs... )

max_stars_repo_name: andreaskoher/CovidSurvey

max_issues_repo_name: andreaskoher/CovidSurvey

max_forks_repo_name: andreaskoher/CovidSurvey


text:
using MathOptInterface
const MOI = MathOptInterface

struct DIRCOLProblemMT{T} <: MOI.AbstractNLPEvaluator
    prob::Problem{T,Continuous}
    cost::Function
    cost_gradient!::Function
    solver::DIRCOLSolverMT{T,HermiteSimpson}
    jac_struct
    part_z::NamedTuple{(:X,:U,:H), NTuple{3,Matrix{Int}}}
    p::NTuple{4,Int}    # (total constraints, p_colloc, p_custom, p_h)
    nG::NTuple{4,Int}   # (total constraint jacobian, nG_colloc, nG_custom, nG_h)
end

function DIRCOLProblemMT(prob::Problem{T,Continuous}, solver::DIRCOLSolverMT{T,HermiteSimpson}) where T
    n,m,N = size(prob)
    p = num_constraints(prob)
    p_colloc = num_colloc(prob)
    p_custom = sum(p)
    p_h = N-2
    P = p_colloc + p_custom + p_h

    NN = N*(n+m) + (N-1)

    nG_colloc = p_colloc*2*(n + m) + p_colloc
    nG_custom = sum(p[1:N-1])*(n+m) + p[N]*n
    nG_h = (N-2)*2
    nG = nG_colloc + nG_custom + nG_h

    part_z = create_partition(n,m,1,N,N,N-1)

    jac_struct_colloc = collocation_constraint_jacobian_sparsityMT!(prob)
    jac_struct_custom = custom_constraint_jacobian_sparsityMT!(prob,p_colloc)
    jac_struct_h = h_eq_constraint_sparsityMT!(prob,p_colloc+p_custom)

    jac_struct = copy(jac_struct_colloc)
    append!(jac_struct,jac_struct_custom)
    append!(jac_struct,jac_struct_h)

    num_con = (P,p_colloc,p_custom,p_h)
    num_jac = (nG, nG_colloc, nG_custom, nG_h)
    DIRCOLProblemMT(prob, gen_stage_cost_min_time(prob,solver.opts.R_min_time), gen_stage_cost_gradient_min_time(prob,solver.opts.R_min_time), solver, jac_struct, part_z, num_con, num_jac)
end

MOI.features_available(d::DIRCOLProblemMT) = [:Grad, :Jac]
MOI.initialize(d::DIRCOLProblemMT, features) = nothing

MOI.jacobian_structure(d::DIRCOLProblemMT) = d.jac_struct
MOI.hessian_lagrangian_structure(d::DIRCOLProblemMT) = []

function MOI.eval_objective(d::DIRCOLProblemMT, Z)
    X,U,H = unpackMT(Z, d.part_z)
    d.cost(X, U, H)
end

function MOI.eval_objective_gradient(d::DIRCOLProblemMT, grad_f, Z)
    X,U,H = unpackMT(Z, d.part_z)
    d.cost_gradient!(grad_f,X,U,H)
end

function MOI.eval_constraint(d::DIRCOLProblemMT, g, Z)
    X,U,H = unpackMT(Z, d.part_z)
    P,p_colloc,p_custom,p_h = d.p
    g_colloc = view(g, 1:p_colloc)
    g_custom = view(g, p_colloc .+ (1:p_custom))
    g_h = view(g, (p_colloc+p_custom) .+ (1:p_h))

    collocation_constraints!(g_colloc, d.prob, d.solver, X, U, H)
    update_constraints!(g_custom, d.prob, d.solver, X, U)
    h_eq_constraints!(g_h,d.prob,d.solver,H)
end

function MOI.eval_constraint_jacobian(d::DIRCOLProblemMT, jac, Z)
    X,U,H = unpackMT(Z, d.part_z)
    n,m = size(d.prob)
    P, p_colloc, p_custom, p_h = d.p
    nG, nG_colloc, nG_custom, nG_h = d.nG
    jac_colloc = view(jac, 1:nG_colloc)
    jac_custom = view(jac, nG_colloc .+ (1:nG_custom))
    jac_h = view(jac, (nG_colloc+nG_custom) .+ (1:nG_h))

    collocation_constraint_jacobian!(jac_colloc, d.prob, d.solver, X, U, H)
    constraint_jacobian!(jac_custom, d.prob, d.solver, X, U)
    h_eq_constraint_jacobian!(jac_h,d.prob,d.solver,H)
end

MOI.eval_hessian_lagrangian(::DIRCOLProblemMT, H, x, σ, μ) = nothing

function solve_moi(prob::Problem, opts::DIRCOLSolverMTOptions)
    prob = copy(prob)
    bnds = remove_bounds!(prob)
    z_U, z_L, g_U, g_L = get_boundsMT(prob, bnds, opts.h_max, opts.h_min)
    n,m,N = size(prob)
    NN = (n+m)*N + (N-1)

    # Get initial condition
    Z0 = PrimalsMT(prob, true)

    # Create NLP Block
    has_objective = true
    dircol = DIRCOLSolverMT(prob, opts)
    d = DIRCOLProblemMT(prob, dircol)
    nlp_bounds = MOI.NLPBoundsPair.(g_L, g_U)
    block_data = MOI.NLPBlockData(nlp_bounds, d, has_objective)

    # Create solver
    solver = typeof(opts.nlp)(;opts.opts...)
    Z = MOI.add_variables(solver, NN)

    # Add bound constraints
    for i = 1:NN
        zi = MOI.SingleVariable(Z[i])
        MOI.add_constraint(solver, zi, MOI.LessThan(z_U[i]))
        MOI.add_constraint(solver, zi, MOI.GreaterThan(z_L[i]))
        MOI.set(solver, MOI.VariablePrimalStart(), Z[i], Z0.Z[i])
    end

    # Solve the problem
    @info "DIRCOL solve using " * String(nameof(parentmodule(typeof(solver))))
    MOI.set(solver, MOI.NLPBlock(), block_data)
    MOI.set(solver, MOI.ObjectiveSense(), MOI.MIN_SENSE)
    MOI.optimize!(solver)

    # Get the solution
    res = MOI.get(solver, MOI.VariablePrimal(), Z)
    res = PrimalsMT(res, d.part_z)

    d.solver.Z = res
    d.solver.stats[:status] = MOI.get(solver, MOI.TerminationStatus())

    # Return the results
    return d.solver
end

function solve!(prob::Problem,opts::DIRCOLSolverMTOptions)
    dircol = solve_moi(prob, opts)

    copyto!(prob.X,dircol.Z.X)
    prob.U = [k != prob.N ? [dircol.Z.U[k];sqrt(dircol.Z.H[k])] : dircol.Z.U[k] for k = 1:prob.N]

    return dircol
end

max_issues_repo_name: MehrdadZareian/GMARA

max_forks_repo_name: MehrdadZareian/GMARA