text:
using Test
using DICOM

const data_folder = joinpath(@__DIR__, "testdata")
if !isdir(data_folder)
    mkdir(data_folder)
end

const dicom_samples = Dict(
    "CT_Explicit_Little.dcm" =>
        "https://github.com/notZaki/DICOMSamples/raw/master/DICOMSamples/CT_Explicit_Little.dcm",
    "CT_Implicit_Little_Headless_Retired.dcm" =>
        "https://github.com/notZaki/DICOMSamples/raw/master/DICOMSamples/CT_Implicit_Little_Headless_Retired.dcm",
    "MG_Explicit_Little.dcm" =>
        "https://github.com/notZaki/DICOMSamples/raw/master/DICOMSamples/MG_Explicit_Little.dcm",
    "MR_Explicit_Little_MultiFrame.dcm" =>
        "https://github.com/notZaki/DICOMSamples/raw/master/DICOMSamples/MR_Explicit_Little_MultiFrame.dcm",
    "MR_Implicit_Little.dcm" =>
        "https://github.com/notZaki/DICOMSamples/raw/master/DICOMSamples/MR_Implicit_Little.dcm",
    "MR_UnspecifiedLength.dcm" =>
        "https://github.com/notZaki/DICOMSamples/raw/master/DICOMSamples/MR_UnspecifiedLength.dcm",
    "OT_Implicit_Little_Headless.dcm" =>
        "https://github.com/notZaki/DICOMSamples/raw/master/DICOMSamples/OT_Implicit_Little_Headless.dcm",
    "US_Explicit_Big_RGB.dcm" =>
        "https://github.com/notZaki/DICOMSamples/raw/master/DICOMSamples/US_Explicit_Big_RGB.dcm",
    "DX_Implicit_Little_Interleaved.dcm" =>
        "https://github.com/OHIF/viewer-testdata/raw/master/dcm/zoo-exotic/5.dcm",
)

function download_dicom(filename; folder = data_folder)
    @assert haskey(dicom_samples, filename)
    url = dicom_samples[filename]
    filepath = joinpath(folder, filename)
    if !isfile(filepath)
        download(url, filepath)
    end
    return filepath
end

@testset "Reading DICOM" begin
    fileMR = download_dicom("MR_Implicit_Little.dcm")
    fileCT = download_dicom("CT_Explicit_Little.dcm")
    fileMG = download_dicom("MG_Explicit_Little.dcm")

    dcmMR_partial = dcm_parse(fileMR, max_group = 0x0008)
    dcmMR = dcm_parse(fileMR)
    dcmCT = dcm_parse(fileCT)
    (dcmMG, vrMG) = dcm_parse(fileMG, return_vr = true)

    @test dcmMR_partial[(0x0008, 0x0060)] == "MR"
    @test haskey(dcmMR_partial, (0x7FE0, 0x0010)) == false

    @test dcmMR[(0x0008, 0x0060)] == "MR"
    @test dcmCT[(0x0008, 0x0060)] == "CT"
    @test dcmMG[(0x0008, 0x0060)] == "MG"

    @test length(dcmMR[(0x7FE0, 0x0010)]) == 65536
    @test length(dcmCT[(0x7FE0, 0x0010)]) == 262144
    @test length(dcmMG[(0x7FE0, 0x0010)]) == 262144

    # Test lookup-by-fieldname
    @test dcmMR[(0x0008, 0x0060)] == lookup(dcmMR, "Modality")
    @test dcmMR[(0x7FE0, 0x0010)] == lookup(dcmMR, "Pixel Data")
end

@testset "Writing DICOM" begin
    fileMR = download_dicom("MR_Implicit_Little.dcm")
    fileCT = download_dicom("CT_Explicit_Little.dcm")
    fileMG = download_dicom("MG_Explicit_Little.dcm")

    dcmMR = dcm_parse(fileMR)
    dcmCT = dcm_parse(fileCT)
    (dcmMG, vrMG) = dcm_parse(fileMG, return_vr = true)

    # Define two output files for each dcm - data will be saved, reloaded, then saved again
    outMR1 = joinpath(data_folder, "outMR1.dcm")
    outMR2 = joinpath(data_folder, "outMR2.dcm")
    outCT1 = joinpath(data_folder, "outCT1.dcm")
    outCT2 = joinpath(data_folder, "outCT2.dcm")
    outMG1 = joinpath(data_folder, "outMG1.dcm")
    outMG1b = joinpath(data_folder, "outMG1b.dcm")
    outMG2 = joinpath(data_folder, "outMG2.dcm")

    # Write DICOM files
    dcm_write(outMR1, dcmMR)
    dcm_write(outCT1, dcmCT)
    dcm_write(outMG1, dcmMG; aux_vr = vrMG)
    open(outMG1b, "w") do io
        dcm_write(io, dcmMG; aux_vr = vrMG)
    end
    # Reading DICOM files which were written from previous step
    dcmMR1 = dcm_parse(outMR1)
    dcmCT1 = dcm_parse(outCT1)
    (dcmMG1, vrMG1) = dcm_parse(outMG1, return_vr = true)
    # Write DICOM files which were re-read from previous step
    dcm_write(outMR2, dcmMR1)
    dcm_write(outCT2, dcmCT1)
    dcm_write(outMG2, dcmMG1; aux_vr = vrMG1)

    # Test consistency of written files after the write-read-write cycle
    @test read(outMR1) == read(outMR2)
    @test read(outCT1) == read(outCT2)
    @test read(outMG1) == read(outMG2)

    # Repeat first testset on written data
    @test dcmMR1[(0x0008, 0x0060)] == "MR"
    @test dcmCT1[(0x0008, 0x0060)] == "CT"
    @test dcmMG1[(0x0008, 0x0060)] == "MG"

    @test length(dcmMR1[(0x7FE0, 0x0010)]) == 65536
    @test length(dcmCT1[(0x7FE0, 0x0010)]) == 262144
    @test length(dcmMG1[(0x7FE0, 0x0010)]) == 262144

    # Test lookup-by-fieldname; cross-compare dcmMR with dcmMR1
    @test dcmMR1[(0x0008, 0x0060)] == lookup(dcmMR, "Modality")
    @test dcmMR1[(0x7FE0, 0x0010)] == lookup(dcmMR, "Pixel Data")
end

@testset "Uncommon DICOM" begin
    # 1. DICOM file with missing preamble
    fileOT = download_dicom("OT_Implicit_Little_Headless.dcm")
    dcmOT = dcm_parse(fileOT, preamble = false)
    @test dcmOT[(0x0008, 0x0060)] == "OT"

    # 2. DICOM file with missing preamble and retired DICOM elements
    fileCT = download_dicom("CT_Implicit_Little_Headless_Retired.dcm")
    # 2a. Read with user-supplied VRs
    dVR_CTa = Dict(
        (0x0008, 0x0010) => "SH",
        (0x0008, 0x0040) => "US",
        (0x0008, 0x0041) => "LO",
        (0x0018, 0x1170) => "DS",
        (0x0020, 0x0030) => "DS",
        (0x0020, 0x0035) => "DS",
        (0x0020, 0x0050) => "DS",
        (0x0020, 0x0070) => "LO",
        (0x0028, 0x0005) => "US",
        (0x0028, 0x0040) => "CS",
        (0x0028, 0x0200) => "US",
    )
    dcmCTa = dcm_parse(fileCT, preamble = false, aux_vr = dVR_CTa)
    # 2b. Read with a master VR which skips elements
    # Here we skip the element (0x0028, 0x0040)
    # and we also force (0x0018,0x1170) to be read as float instead of integer
    dVR_CTb = Dict((0x0028, 0x0040) => "", (0x0018, 0x1170) => "DS")
    dcmCTb = dcm_parse(fileCT, preamble = false, aux_vr = dVR_CTb)
    @test dcmCTa[(0x0008, 0x0060)] == "CT"
    @test dcmCTb[(0x0008, 0x0060)] == "CT"
    @test haskey(dcmCTa, (0x0028, 0x0040)) # dcmCTa should contain retired element
    @test !haskey(dcmCTb, (0x0028, 0x0040)) # dcmCTb skips retired elements

    rescale!(dcmCTa)
    @test minimum(dcmCTa[(0x7fe0, 0x0010)]) == -949
    @test maximum(dcmCTa[(0x7fe0, 0x0010)]) == 1132
    rescale!(dcmCTa, :backward)
    @test minimum(dcmCTa[(0x7fe0, 0x0010)]) == minimum(dcmCTb[(0x7fe0, 0x0010)])
    @test maximum(dcmCTa[(0x7fe0, 0x0010)]) == maximum(dcmCTb[(0x7fe0, 0x0010)])

    # 3. DICOM file containing multiple frames
    fileMR_multiframe = download_dicom("MR_Explicit_Little_MultiFrame.dcm")
    dcmMR_multiframe = dcm_parse(fileMR_multiframe)
    @test dcmMR_multiframe[(0x0008, 0x0060)] == "MR"

    # 4. DICOM with unspecified_length()
    fileMR_UnspecifiedLength = download_dicom("MR_UnspecifiedLength.dcm")
    dcmMR_UnspecifiedLength = dcm_parse(fileMR_UnspecifiedLength)
    @test size(dcmMR_UnspecifiedLength[tag"Pixel Data"]) === (256, 256, 27)
end

@testset "Test big endian" begin
    fileUS = download_dicom("US_Explicit_Big_RGB.dcm")
    dcmUS = dcm_parse(fileUS)
    @test Int(dcmUS[(0x7fe0, 0x0000)]) == 921612
    @test size(dcmUS[(0x7fe0, 0x0010)]) == (480, 640, 3)
end

@testset "Test interleaved" begin
    fileDX = download_dicom("DX_Implicit_Little_Interleaved.dcm")
    dcmDX = dcm_parse(fileDX)
    @test size(dcmDX[(0x7fe0, 0x0010)]) == (1590, 2593, 3)
end

@testset "DICOMData API" begin
    dcmFile = download_dicom("MR_Implicit_Little.dcm")
    dcm = dcm_parse(dcmFile)
    @test length(keys(dcm)) == 87
    @test haskey(dcm, "PatientName")
    @test haskey(dcm, :PatientName)
    @test haskey(dcm, (0x0010, 0x0010))
    @test dcm.PatientName ===
          dcm[:PatientName] ===
          dcm["PatientName"] ===
          dcm[(0x0010, 0x0010)] ===
          "Anonymized"
    dcm.PatientName = "Tom"
    @test dcm.PatientName == "Tom"
    dcm[:PatientName] = "Dick"
    @test dcm.PatientName == "Dick"
    dcm["PatientName"] = "Harry"
    @test dcm.PatientName == "Harry"
    dcm[(0x0010, 0x0010)] = "Anonymized"
    @test dcm.PatientName ===
          dcm[:PatientName] ===
          dcm["PatientName"] ===
          dcm[(0x0010, 0x0010)] ===
          "Anonymized"
end

@testset "Parse entire folder" begin
    # Following files have missing preamble and won't be parsed
    # ["OT_Implicit_Little_Headless.dcm", "CT_Implicit_Little_Headless_Retired.dcm"]
    dcms = dcmdir_parse(data_folder)
    @test issorted([dcm[tag"Instance Number"] for dcm in dcms])
    @test length(dcms) == length(readdir(data_folder)) - 2 # -2 because of note above
end

@testset "Test tag macro" begin
    @test tag"Modality" === (0x0008, 0x0060) === DICOM.fieldname_dict[:Modality]
    @test tag"Shutter Overlay Group" ===
          (0x0018, 0x1623) ===
          DICOM.fieldname_dict[:ShutterOverlayGroup]
    @test tag"Histogram Last Bin Value" === (0x0060, 0x3006)
    DICOM.fieldname_dict[:HistogramLastBinValue]

    # test that compile time error is thrown if tag does not exist
    @test macroexpand(Main, :(tag"Modality")) === (0x0008, 0x0060)
    @test_throws LoadError macroexpand(Main, :(tag"nonsense"))
end


text:
module ModelTuneCF

using Persa

# package code goes here
include("gridsearch.jl")
include("ga.jl")

end # module

ext: jl

max_stars_repo_name: JuliaRecsys/ModelTuneCF

max_issues_repo_name: JuliaRecsys/ModelTuneCF

max_forks_repo_name: JuliaRecsys/ModelTuneCF


text:
__precompile__()

module DocSeeker

export searchdocs

using StringDistances, Hiccup, Requires
using REPL: stripmd
import Markdown

# TODO: figure out how to get something useable out of `DocObj.sig`
# TODO: figure out how to save `sig` and not kill serialization
struct DocObj
  name::String
  mod::String
  typ::String
  # sig::Any
  text::String
  html::Markdown.MD
  path::String
  line::Int
  exported::Bool
end

function Base.hash(s::DocObj, h::UInt)
  hash(s.name, hash(s.mod, hash(s.typ, hash(s.text, hash(s.exported, hash(s.line,
       hash(s.path, hash(:DocObj, h))))))))
end
function Base.:(==)(a::DocObj, b::DocObj)
  isequal(a.name, b.name) && isequal(a.mod, b.mod) && isequal(a.typ, b.typ) &&
  isequal(a.text, b.text) && isequal(a.path, b.path) && isequal(a.line, b.line) &&
  isequal(a.exported, b.exported)
end

# TODO: better string preprocessing.
"""
    score(needle, s::Docs.DocObj) -> Float

Scores `s` against the search query `needle`. Returns a `Float` between 0 and 1.
"""
function score(needle::String, s::DocObj, name_only = false)
  score = 0.0
  length(needle) == 0 && return score

  needles = split(needle, ' ')
  binding_score = length(needles) > 1 ? 0.0 : compare(needle, s.name, Winkler(Jaro()))
  c_binding_score = length(needles) > 1 ? 0.0 : compare(lowercase(needle), lowercase(s.name), Winkler(Jaro()))

  if name_only
    score = c_binding_score
  else
    docs_score = compare(lowercase(needle), lowercase(s.text), TokenSet(Jaro()))

    # bonus for exact case-insensitive binding match
    binding_weight = c_binding_score == 1.0 ? 0.95 : 0.7

    score += binding_weight*c_binding_score + (1 - binding_weight)*docs_score
  end

  # penalty if cases don't match
  binding_score < c_binding_score && (score *= 0.98)
  # penalty if binding has no docs
  length(s.text) == 0 && (score *= 0.85)
  # penalty if binding isn't exported
  s.exported || (score *= 0.99)

  return score
end

# console rendering
function Base.show(io::IO, d::DocObj)
  println(io, string(d.mod, '.', d.name, " @$(d.path):$(d.line)"))
end

function Base.show(io::IO, ::MIME"text/plain", d::DocObj)
  println(io, string(d.mod, '.', d.name, " @$(d.path):$(d.line)"))
  println(io)
  println(io, d.text)
end

include("introspective.jl")
include("finddocs.jl")
include("static.jl")
include("documenter.jl")

function __init()__
  # improved rendering if used in Atom:
  @require Atom="c52e3926-4ff0-5f6e-af25-54175e0327b1" begin
    function Atom.render(i::Atom.Inline, d::DocObj)
      Atom.render(i, Atom.Tree(span(span(".syntax--support.syntax--function", d.name),
                                    span(" @ $(d.path):$(d.line)")), [Atom.render(i, Atom.renderMD(d.html))]))
    end
  end
end

end # module


text:
using MixedModels, RData, Test

if !@isdefined(dat) || !isa(dat, Dict{Symbol, DataFrame})
    const dat = Dict(Symbol(k) => v for (k, v) in
        load(joinpath(dirname(pathof(MixedModels)), "..", "test", "dat.rda")))
end

# deepcopy because we're going to modify it
slp = deepcopy(dat[:sleepstudy])
slp[!,:U] = Array{Union{Missing, Float64},1}(slp[!,:U])
slp[1,:U] = missing

# TODO: re-enable this test when better missing support has landed in StatsModels
# @testset "No impact from missing on schema" begin
#     f = @formula(Y ~ 1 + U + (1|G))
#     contrasts =  Dict{Symbol,Any}()
#     form = apply_schema(f, schema(f, dat[:sleepstudy], contrasts), LinearMixedModel)
#     form_missing = apply_schema(f, schema(f, slp, contrasts), LinearMixedModel)
#
#     @test form.lhs == form_missing.lhs
#     @test form.rhs == form_missing.rhs
# end

@testset "Missing Omit" begin
    @testset "Missing from unused variables" begin
        # missing from unused variables should have no impact
        m1 = fit(MixedModel, @formula(Y ~ 1 + (1|G)), dat[:sleepstudy])
        m1_missing = fit(MixedModel, @formula(Y ~ 1 + (1|G)), slp)
        @test isapprox(m1.θ, m1_missing.θ, rtol=1.0e-12)
    end

    @testset "Missing from used variables" begin
        m1 = fit(MixedModel, @formula(Y ~ 1 + U + (1|G)), dat[:sleepstudy])
        m1_missing = fit(MixedModel, @formula(Y ~ 1 + U + (1|G)), slp)
        @test nobs(m1) - nobs(m1_missing) == 1
    end
end


text:
🦀 = parse.(Int, split(read("input.txt", String), ","))
fuel1, fuel2 = typemax(Int), typemax(Int)
for loc in minimum(🦀):maximum(🦀)
    fuel1 = min(fuel1, sum(x -> abs(x - loc), 🦀))
    fuel2 = min(fuel2, sum(x -> sum(1:abs(x - loc)), 🦀))
end
@info "Part 1: minimum fuel usage = $fuel1"
@info "Part 2: minimum fuel usage = $fuel2"


text:
##############   EXAMPLE-2     ##############
# Correlated errors in X and Y

using LinearFitXYerrors
using Plots; gr()

# INPUT DATA:
# Amen, S. [2012] Linear estimation for data with error ellipses. MSc. Statistics, Univ. of Texas

#  Table 3.1

# Num,    ue,    n,   var_ue,   var_n,   cov_ue_n
M = [1   23.371   5.992   0.106   0.323   0.170;
    2    24.462   8.899   1.692   10.195  3.887;
    3    22.414   5.361   0.124   0.460   0.207;
    4    27.628   10.271  1.088   1.460   1.255;
    5    23.802   7.114   0.107   0.496   0.191;
    6    23.092   7.975   0.281   1.651   0.582;
    7    23.263   7.486   0.316   1.695   0.661;
    8    20.843   4.169   0.389   0.335   0.357;
    9    24.421   5.645   0.381   0.716   0.507;
    10   23.716   9.220   0.733   3.656   1.401;
    11   22.032   5.358   0.094   0.268   0.106;
    12   21.448   3.166   0.167   0.170   0.001;
    13   21.631   4.002   0.127   0.106   0.082;
    14   19.947   2.073   0.015   0.015   0.001;
    15   20.652   3.338   0.040   0.104   0.021;
    16   20.588   2.028   0.007   0.011   0.002;
    17   20.745   1.978   0.010   0.010  -0.001;
    18   21.658   2.526   0.009   0.058  -0.003;
    19   19.539   2.043   0.044   0.070  -0.039;
    20   21.638   3.361   1.909   3.961  -2.557;
    21   19.863   2.452   0.014   0.019  -0.010;
    22   18.398   2.199   0.042   0.051  -0.037;
    23   20.729   1.725   0.013   0.026   0.003;
    24   20.511   1.906   0.003   0.010   0.001;
    25   22.140   3.372   0.047   0.108   0.062;
    26   20.510   2.130   0.004   0.020   0.002;
    27   20.141   1.897   0.006   0.011  -0.005]

μₑ = M[:,2]
η = M[:,3]
σμₑ = sqrt.(M[:,4])   # standard deviation of errors in μₑ
ση = sqrt.(M[:,5])     # standard deviation of errors in η
cov_μₑ_η = M[:,6]   # covariance between errors in μₑ and η
r = cov_μₑ_η ./ (σμₑ .* ση )   # correlation coefficient between errors

# COMPUTE and PLOT:
# The standard deviation errors using York (2004) are >> than Amen (2012)
# However, Amen (2012) errors seem to be underestimated - tbc

stxy = linearfitxy(μₑ, η; σX=σμₑ, σY=ση, r=r, isplot=true)

# If assuming no errors:
st = linearfitxy(μₑ, η);

# If assuming only errors in Y or in X:
sty = linearfitxy(μₑ, η; σX=0, σY=ση, r=r);
stx = linearfitxy(μₑ, η; σX=σμₑ, σY=0, r=r);

dX = diff([extrema(μₑ)...])[1]/7
x1, x2 = (-dX, dX) .+ extrema(μₑ)
xx = [x1; μₑ; x2]
plot!(xx, st.a .+ st.b*xx, color=:pink, lw=0.5, label="LinearFitXY (no errors)");
plot!(xx, sty.a .+ sty.b*xx, color=:lime, lw=0.5, label="LinearFitXY (Y errors)");
plot!(xx, stx.a .+ stx.b*xx, color=:orange, lw=0.5, label="LinearFitXY (X errors)");

# Compare with LsqFit:
using LsqFit
m(x, p) = p[1] .+ p[2] * x
p0 = [0., 0.]
fit2 = curve_fit(m, μₑ, η, p0)
cf2 = coef(fit2)
ci2 = confidence_interval(fit2, 0.05)    # 5% significance level
@printf("LsqFit (no errors): Y = (%.2f ± %.2f) + (%.2f ± %.2f)*X",
          cf2[1],diff([ci2[1]...])[1]/2, cf2[2],diff([ci2[2]...])[1]/2)

wt3 = 1 ./ ση .^2
fit3 = curve_fit(m, μₑ, η, wt3, p0)
cf3 = coef(fit3)
ci3 = confidence_interval(fit3, 0.05)    # 5% significance level
@printf("LsqFit (Y-errors): Y = (%.2f ± %.2f) + (%.2f ± %.2f)*X",
          cf3[1],diff([ci3[1]...])[1]/2, cf3[2],diff([ci3[2]...])[1]/2)

wt4 = 1 ./ σμₑ .^2
fit4 = curve_fit(m, η, μₑ, wt4, p0)     # fit X function of Y
cf4 = coef(fit4)
cf4[1] = -cf4[1] / cf4[2]       # convert coefficients to Y = a + b*X form
cf4[2] = 1 / cf4[2]
ci4 = confidence_interval(fit4, 0.05)    # 5% significance level
@printf("LsqFit (X-errors): Y = (%.2f ± %.2f) + (%.2f ± %.2f)*X",
          cf4[1],diff([ci4[1]...])[1]/2, cf4[2],diff([ci4[2]...])[1]/2)

plot!(xx, cf2[1] .+ cf2[2]*xx, lw=0.5, lc=:red, ls=:dash, label="LsqFit (no errors)")
plot!(xx, cf3[1] .+ cf3[2]*xx, color=:darkgreen, lw=0.5, ls=:dash, label="LsqFit (Y-errors)")
plot!(xx, cf4[1] .+ cf4[2]*xx, color=:darkred, lw=0.5, ls=:dash, label="LsqFit (X-errors)")

savefig("Example2_LinearFitXYerrors.png")
########################################


text:
module TestOptics

using Accessors
using Test

@testset "Properties" begin
    pt = (x=1, y=2, z=3)
    @test (x=0, y=1, z=2) === @set pt |> Properties() -= 1
end

@testset "Elements" begin

    @test [0,0,0] == @set 1:3 |> Elements() = 0

    arr = 1:3
    @test 2:4 == (@set arr |> Elements() += 1)
    @test map(cos, arr) == modify(cos, arr, Elements())

    @test modify(cos, (), Elements()) === ()

    @inferred modify(cos, arr, Elements())
    @inferred modify(cos, (), Elements())
end

@testset "Recursive" begin
    obj = (a=1, b=(1,2), c=(A=1, B=(1,2,3), D=4))
    rp = Recursive(x -> !(x isa Tuple), Properties())
    @test modify(collect, obj, rp) == (a = 1, b = [1, 2], c = (A = 1, B = [1, 2, 3], D = 4))

    arr = [1,2,[3,4], [5, 6:7,8, 9,]]
    oc = Recursive(x -> x isa AbstractArray, Elements())
    expected = [0,1,[2,3], [4, 5:6,7, 8,]]
    @test modify(x-> x - 1, arr, oc) == expected
end

@testset "If" begin
    @test 10 === @set(1 |> If(>=(0)) = 10)
    @test -1 === @set(-1 |> If(>=(0)) = 10)
    @inferred set(1, If(iseven), 2)
    @inferred modify(x -> 0, 1, If(iseven))

    arr = 1:6
    @test [1, 0, 3, 0, 5, 0] == @set(arr |> Elements() |> If(iseven) = 0)
    @inferred modify(x -> 0, arr, @optic _ |> Elements() |> If(iseven))
end

end#module


text:
include("gc.jl")
include("test.jl")


text:
using OmegaCore
using Test
using Random
using OmegaCore.Tagging
using OmegaCore.Traits
using OmegaCore.RNG
using OmegaCore.TrackError

tagmersenne(ω) = tagrng(ω, Random.MersenneTwister())

@testset "tagging" begin

@testset "tagging1" begin
  ω = defΩ()()
  ω = tagmersenne(ω)
  ω = tagerror(ω, false)
  t_ = traits(ω)
  @test t_ == Trait{Union{Err, Rng}}()
end

@testset "tagging2" begin
  ω = defΩ()()
  ω2 = tagmersenne(ω)
  f(x::trait(Rng)) = 1
  f(_) = 2
  @test f(traits(ω)) == 2
  @test f(traits(ω2)) == 1
  @test isinferred(f, traits(ω))
  @test isinferred(f, traits(ω2))
end

@testset "tagging3" begin
  ω = defω()
  f(x::trait(Cond, Rng)) = 1
  f(x::trait(Cond, Mem)) = 2
  @test_throws MethodError f(ω)
end

@testset "tagging4" begin
  ω = defΩ()()
  ω2 = tagmersenne(ω)
  f(x::trait(Cond, Rng)) = 1
  f(x::trait(Cond, Mem)) = 2
  @test_throws MethodError f(traits(ω2))
end

@testset "tagging5" begin
  ω = defΩ()()
  ω = tagmersenne(ω)
  ω = tagerror(ω, false)
  g(x::trait(Rng)) = 1
  g(x::trait(Err)) = 2
  @test_throws MethodError g(traits(ω))
end

end

max_stars_repo_name: zenna/expect

max_issues_repo_name: zenna/expect

max_forks_repo_name: zenna/expect


text:
function semi_infinite_transform(f, a, b, args)
    if b == Inf
        return (y)->f(a+y/(1-y), args...)/(1-y)^2, 0.0, 1.0
    elseif b == -Inf
        return (y)->f(a+(1-y)/y, args...)/y^2, 1.0, 0.0
    elseif a == Inf
        return (y)->f(b+y/(1-y), args...)/(1-y)^2, 1.0, 0.0
    elseif a == -Inf
        return (y)->f(b+(1-y)/y, args...)/y^2, 0.0, 1.0
    else
        @error "Invalid integration limit"
    end
end

function infinite_transformation(f, a, b, args)
    if a == b
        @error "Invalid integration limit"
    else
        lower_limit = a < 0 ? 0.0 : 1.0
        upper_limit = 1.0 - lower_limit
    end
    (y)->f((2*y-1)/(1-y)/y, args...)*(2*y^2-2*y+1)/(1-y)^2/y^2, lower_limit, upper_limit
end

function integral_limit_transfromation(f, a, b, args)
    if isfinite(a) && isfinite(b)
        return (y)->f(y, args...), a, b
    elseif !isfinite(a) && !isfinite(b)
        return infinite_transformation(f, a, b, args)
    else
        return semi_infinite_transform(f, a, b, args)
    end
end


text:
export Chebyshev

immutable Chebyshev{D<:Domain} <: PolynomialSpace{D}
    domain::D
    Chebyshev(d) = new(d)
    Chebyshev() = new(Interval())
end

Chebyshev() = Chebyshev{Interval{Float64}}()
Chebyshev(d::Domain) = Chebyshev{typeof(d)}(d)
Chebyshev(d::Vector) = Chebyshev(Domain(d))

Space(d::Interval) = Chebyshev(d)

setdomain(S::Chebyshev,d::Domain) = Chebyshev(d)

Base.ones{T<:Number}(::Type{T},S::Chebyshev) = Fun(ones(T,1),S)
Base.ones(S::Chebyshev) = Fun(ones(1),S)

Base.first{D}(f::Fun{Chebyshev{D}}) = foldr(-,coefficients(f))
Base.last{D}(f::Fun{Chebyshev{D}}) = reduce(+,coefficients(f))
identity_fun(d::Chebyshev) = identity_fun(domain(d))

spacescompatible(a::Chebyshev,b::Chebyshev) = domainscompatible(a,b)
hasfasttransform(::Chebyshev) = true

function coefficients(g::Vector,::ConstantSpace,::Chebyshev)
    @assert length(g)==1
    g
end

function coefficients(g::Vector,::Chebyshev,::ConstantSpace)
    @assert length(g)==1
    g
end

## Transform

transform(::Chebyshev,vals::Vector,plan) = chebyshevtransform(vals,plan)
itransform(::Chebyshev,cfs::Vector,plan) = ichebyshevtransform(cfs,plan)
plan_transform(::Chebyshev,vals::Vector) = plan_chebyshevtransform(vals)
plan_itransform(::Chebyshev,cfs::Vector) = plan_ichebyshevtransform(cfs)

## Evaluation

clenshaw(sp::Chebyshev,c::AbstractVector,x::AbstractArray) =
    clenshaw(c,x,ClenshawPlan(promote_type(eltype(c),eltype(x)),sp,length(c),length(x)))

function clenshaw(::Chebyshev,c::AbstractVector,x)
    N,T = length(c),promote_type(eltype(c),typeof(x))
    if isempty(c)
        return zero(x)
    end

    x = 2x
    bk1,bk2 = zero(T),zero(T)
    for k = N:-1:2
        bk2, bk1 = bk1, muladd(x,bk1,c[k]-bk2)
    end

    muladd(x/2,bk1,c[1]-bk2)
end

clenshaw{S<:Chebyshev,V}(c::AbstractVector,x::AbstractVector,plan::ClenshawPlan{S,V})=
    clenshaw(c,collect(x),plan)

#TODO: This modifies x, which is not threadsafe
function clenshaw{S<:Chebyshev,V}(c::AbstractVector,x::Vector,plan::ClenshawPlan{S,V})
    N,n = length(c),length(x)
    if isempty(c)
        return zeros(V,n)
    end

    bk=plan.bk
    bk1=plan.bk1
    bk2=plan.bk2

    @inbounds for i = 1:n
        x[i] = 2x[i]
        bk1[i] = zero(V)
        bk2[i] = zero(V)
    end

    @inbounds for k = N:-1:2
        ck = c[k]
        for i = 1:n
            bk[i] = muladd(x[i],bk1[i],ck-bk2[i])
        end
        bk2, bk1, bk = bk1, bk, bk2
    end

    ck = c[1]
    @inbounds for i = 1:n
        x[i] = x[i]/2
        bk[i] = muladd(x[i],bk1[i],ck-bk2[i])
    end

    bk
end

function clenshaw{S<:Chebyshev,T<:Number}(c::AbstractMatrix{T},x::T,plan::ClenshawPlan{S,T})
    bk=plan.bk
    bk1=plan.bk1
    bk2=plan.bk2

    m,n=size(c) # m is # of coefficients, n is # of funs

    @inbounds for i = 1:n
        bk1[i] = zero(T)
        bk2[i] = zero(T)
    end
    x = 2x

    @inbounds for k=m:-1:2
        for j=1:n
            ck = c[k,j]
            bk[j] = muladd(x,bk1[j],ck - bk2[j])
        end
        bk2, bk1, bk = bk1, bk, bk2
    end

    x = x/2
    @inbounds for i = 1:n
        ce = c[1,i]
        bk[i] = muladd(x,bk1[i],ce - bk2[i])
    end

    bk
end

function clenshaw{S<:Chebyshev,T<:Number}(c::AbstractMatrix{T},x::AbstractVector{T},plan::ClenshawPlan{S,T})
    bk=plan.bk
    bk1=plan.bk1
    bk2=plan.bk2

    m,n=size(c) # m is # of coefficients, n is # of funs

    @inbounds for i = 1:n
        x[i] = 2x[i]
        bk1[i] = zero(T)
        bk2[i] = zero(T)
    end

    @inbounds for k=m:-1:2
        for j=1:n
            ck = c[k,j]
            bk[j] = muladd(x[j],bk1[j],ck - bk2[j])
        end
        bk2, bk1, bk = bk1, bk, bk2
    end

    @inbounds for i = 1:n
        x[i] = x[i]/2
        ce = c[1,i]
        bk[i] = muladd(x[i],bk1[i],ce - bk2[i])
    end

    bk
end

# overwrite x

function clenshaw!{S<:Chebyshev,V}(c::Vector,x::Vector,plan::ClenshawPlan{S,V})
    N,n = length(c),length(x)

    if isempty(c)
        fill!(x,0)
        return x
    end

    bk=plan.bk
    bk1=plan.bk1
    bk2=plan.bk2

    @inbounds for i = 1:n
        x[i] = 2x[i]
        bk1[i] = zero(V)
        bk2[i] = zero(V)
    end

    @inbounds for k = N:-1:2
        ck = c[k]
        for i = 1:n
            bk[i] = muladd(x[i],bk1[i],ck - bk2[i])
        end
        bk2, bk1, bk = bk1, bk, bk2
    end

    ce = c[1]
    @inbounds for i = 1:n
        x[i] = x[i]/2
        x[i] = muladd(x[i],bk1[i],ce-bk2[i])
    end

    x
end

## Calculus

# diff T -> U, then convert U -> T
integrate{D<:Interval}(f::Fun{Chebyshev{D}}) =
    Fun(fromcanonicalD(f,0)*ultraint!(ultraconversion(f.coefficients)),f.space)
differentiate{D<:Interval}(f::Fun{Chebyshev{D}}) =
    Fun(1/fromcanonicalD(f,0)*ultraiconversion(ultradiff(f.coefficients)),f.space)

## identity_fun

## Multivariate

#TODO: adaptive
for op in (:(Base.sin),:(Base.cos))
    @eval ($op){S<:Chebyshev,V<:Chebyshev}(f::ProductFun{S,V}) =
        ProductFun(chebyshevtransform($op(values(f))),space(f))
end

reverseorientation{C<:Chebyshev}(f::Fun{C}) =
    Fun(alternatesign!(copy(f.coefficients)),Chebyshev(reverse(domain(f))))

include("ChebyshevOperators.jl")


text:
"""
    Board

Parent element which encapsulates all objects (sliders, points, curves, ...).
"""
mutable struct Board
    name::String
    functions::Vector{JSFun}
    objects::Vector{Object}
    # --- key board options ---
    xlim::Vector{<:Real}
    ylim::Vector{<:Real}
    axis::Bool
    showcopyright::Bool
    shownavigation::Bool
    style::String
    # --- other board options --- jsxgraph.org/docs/symbols/JXG.Board.html
    opts::Option{LittleDict{Symbol,Any}}
end
function Board(name, funs, objs;
               xlim=[-10,10], ylim=[-10,10], axis=false,
               showcopyright=false, shownavigation=false,
               style="width:300px; height:300px;", kw...)
    d = dict(;kw...)
    b = Board(name, funs, objs, xlim, ylim, axis,
              showcopyright, shownavigation,
              style, d)
    if !isnothing(d) && :boundingbox ∈ keys(d)
        bb = d[:boundingbox]
        @assert length(bb) == 4 "Bounding box must have 4 elements."
        b.xlim = bb[1,3]
        b.ylim = bb[4,2]
    end
    return b
end

"""
    board(name="brd"+randstring(3); opts...)

Create a new board.

* `name` - name of the board (generated by default)

## Keyword
* `xlim::Vector` - x axis limits default: `[-10,10]`
* `ylim::Vector` - y axis limits default: `[-10,10]`
* `axis::Bool` - whether to show the axis ex: false
* `showcopyright::Bool` - whether to show JSX's copyright ex: true
* `shownavigation::Bool` - whether to show a navigation tool on the board ex:
                            true
* `style::String` - the CSS style of the div containing the board ex:
                     `"width:300px; height:300px;"`

You can also use any of the keywords from https://jsxgraph.org/docs/symbols/JXG.Board.html.
"""
board(name="brd_"*randstring(3); kw...) = Board(name, JSFun[], Object[]; kw...)

# ---------------------------------------------------------------------------

get_opts(b::Board) = (
    boundingbox = [b.xlim[1], b.ylim[2], b.xlim[2], b.ylim[1]],
    axis = b.axis,
    showcopyright = b.showcopyright,
    shownavigation = b.shownavigation,
    (isnothing(b.opts) ? () : (;b.opts...))...
    )

"""
    o |> board
    (o1, o2, ...) |> board
    [o1, o2, ...] |> board

Add object(s) to board `board`.
"""
(b::Board)(j::JSFun)  = push!(b.functions, j)
(b::Board)(o::Object) = push!(b.objects, o)
(b::Board)(o) = (b.(o); b)

"""
    board ++ o

Same as `o |> board`.
"""
++(b::Board, o) = b(o)
++(o, b::Board) = b(o)

"""
    empty!(board)

Removes everything on the board
"""
Base.empty!(b::Board) = (empty!(b.functions); empty!(b.objects); b)

# ---------------------------------------------------------------------------

const PREAMBLE = "function val(x){return x.Value();};" *
    "function valx(p){return p.X();};" *
    "function valy(p){return p.Y();};" *
    "function setxy(o,x,y){o.moveTo([x,y]);};" *
    "function setx(o,x){setxy(o,x,o.Y());};" *
    "function sety(o,y){setxy(o,o.X(),y);};" * prod(
        "function $f(x){return Math.$f(x);};"
        for f in (:abs, :acos, :acosh, :asin, :asinh, :atan, :atanh, :ceil,
                  :cos, :cosh, :exp, :expm1, :floor, :hypot, :log, :log1p,
                  :log10, :log2, :max, :min, :round, :sign, :sin, :sinh,
                  :sqrt, :tan, :tanh, :trunc)) *
    "function rand(){return Math.random();};" *
    "const π=Math.PI;const ℯ=Math.E;const pi=Math.PI;"

function str(b::Board; preamble=true)
    io = IOBuffer()
    # preamble
    preamble && print(io, PREAMBLE)
    # functions
    for f in b.functions
        print(io, str(f))
    end
    # objects
    opts = get_opts(b)
    jss = js"JXG.JSXGraph.initBoard($(b.name),$opts);"
    print(io, "var $(b.name)=" * jss.s)
    for o in b.objects
        print(io, str(o, b))
    end
    s = "(function(){" * String(take!(io)) * "})();"
    return s
end

"""
    save(b, fpath)

Save a board as a javascript file that can be plugged in a HTML file which
would link to the JSXGraph library and stylesheet.
"""
function save(b::Board, fpath::AbstractString)
    fpath = splitext(fpath)[1] * ".js"
    write(fpath, str(b))
    return nothing
end


text:
module Aircrafts
    include("aircrafts/C310.jl")
    include("aircrafts/F16.jl")

    include("trimmer.jl")
    include("Linearization.jl")
end


text:
struct Tree
diameter::Real
height::Union{Real,Missing}
species::Union{AbstractString,Real}
expansion::Real
end


text:
module NullableStats

using NullableArrays
using StatsBase

include("statistics.jl")

end # module

max_stars_repo_name: davidagold/NullableStats

max_issues_repo_name: davidagold/NullableStats

max_forks_repo_name: davidagold/NullableStats


text:
include("BarFrameworks.jl")

V = [1,2,3,4]
E = [(1,2), (2,3), (3,4), (1,4), (1,3)]
edgelengths = Dict((1,2) => 1,
                (2,3) => 1.0,
                (3,4) => 1.0 + 0.0im,
                (1,4) => 1,
                (1,3) => sqrt(2) )
bf = BarFrameworks.BarFramework(V,E,edgelengths,2)
eqnz = BarFrameworks.getBarEquations(bf)

# F = BarFrameworks.getSystem(bf)
# typeof(F)
#
# using HomotopyContinuation
# result = solve(F)
# typeof(result)
# realsols = real_solutions(result)

realizationsresult = BarFrameworks.realizations(bf)

realsol = realizationsresult.realsolutions[1]

mat = BarFrameworks.tomatrix(bf, realsol)

mats = [BarFrameworks.tomatrix(bf, realsol) for realsol in realizationsresult.realsolutions]

import LinearAlgebra
LinearAlgebra.norm(mat[3,:])

minimum(mat[i,1] for i in 1:4)
maximum(mat[i,1] for i in 1:4)

minimum(minimum(mat[i,1] for i in 1:4) for mat in mats)
maximum(maximum(mat[i,1] for i in 1:4) for mat in mats)


text:
#### This script is the highest wrapper, that's why I overcommented it ####
include("./Distribution.jl")
include("./Newton.jl")
include("./Spherical_harmonics.jl")
include("./No_energy_constraint_case.jl")
using LinearAlgebra
using FastGaussQuadrature

function solve_by_energy_sequence(J::Array{Float64, 3}, L::Array{Float64, 1}, N::Array{Float64, 1}, Etot::Float64, Ltot::Float64)
    #### Returns a Distribution. It is the solution to the microcanonical problem Etot, Ltot IF it exists. ####
    #### One should always check that the cost of that dist is less than 10⁻⁶ !                                           ####
    #### This function solves the problem by starting at the β = 0 point which is easy to find,                           ####
    #### then moving through the sequence of equilibrium to the point of interest .                                       ####

    # let's get all the constants we need
    n_pop = size(J)[1] # number of populations
    lmax_half = size(J)[3] # number of interesting modes
    lmax = 2 * lmax_half # number of modes
    n_quad = max(100, 2 * lmax) # number of quadratures
    size_mag = lmax_half * n_pop # size of the magnitudes vector
    size_jac = lmax_half * n_pop + 2 # size of the jacobian matrix

    # let's preallocate the arrays we will need
    List_x , List_w = gausslegendre(n_quad) # will hold the position and weight (respectively) of the quadrature nodes
    List_Y = zeros(lmax_half, n_quad) # Will hold the spherical harmonics

    # let's compute the spherical harmonics
    Pₗ = zeros(lmax_half) # This is temporary (allocates as early as possible an array used by Spherical_harmonics_a!)
    Yₗ = zeros(lmax_half) # this is temporary (allocates as early as possible an array used by Spherical_harmonics_a!)
    for i = 1:n_quad
        Spherical_harmonics_a!(List_x[i], lmax, Yₗ = Yₗ, Pₗ = Pₗ) # Yₗ now holds the spherical harmonics at this point x
        List_Y[:, i] = Yₗ
    end

    # let's get the initial point (β, γ, M)
    β = 0.0
    γ = Solution_no_Etot_dichotomy(L, N, Ltot)
    M = Magnetisations_no_Etot(L, N, γ, lmax, List_x, List_w, List_Y)

    # let's create the initial distribution
    Etot_first_guess = 1.0 # at first, we create a distribution with a mock energy
    dist = Distribution(J, L, N, Etot_first_guess, Ltot, β = β, γ = γ, M = M)

    # let's compute the initial energy and use it to correct the energy of the initial distribution
    Cost_and_Jacobian!(dist)
    Etot_start = Etot_first_guess * (1.0 - dist.cost[1])
    dist.Etot = Etot_start

    # let's choose our steps
    n_steps = 50 # this number is quite arbitrary
    List_Etot = - 10 .^ (range(log10(- Etot_start), stop = log10(- Etot), length = n_steps))

    # let's perform the steps
    for n = 2:n_steps
        dist.Etot = List_Etot[n] # We do not create a new distribution at each step, it would cost too much memory
        Root_finder_Newton!(dist)
    end

    # Let's return the final distribution
    return(dist)
end

max_stars_repo_name: NathanMagnan/VRROOMe

max_issues_repo_name: NathanMagnan/VRROOMe

max_forks_repo_name: NathanMagnan/VRROOMe


text:
using Distributed, Pkg
addprocs(8)
@everywhere using Distributed, Pkg
Pkg.activate(".")
@everywhere Pkg.activate(".")
using LTMSim, DataFrames, SimpleHypergraphs, Statistics, Plots, PyPlot, Random, Serialization, LaTeXStrings
@everywhere using LTMSim, DataFrames, SimpleHypergraphs, Statistics, Random, Serialization

struct Serie
	x::Vector{Float64}
	y::Vector{Float64}
	z::Vector{Float64}
	Serie() = new(Array{Float64,1}(), Array{Float64,1}(),Array{Float64,1}())
end
	default(size=(600,600), fc=:heat)
N = 200
M = 200
r = 20

hr = randomH(N, M)
hk = randomHkuniform(N, M, r)
hd = randomHduniform(N, M, r)
hp = randomHpreferential(N, 0.5)
hg = hg_load("data/got.hgf")

graphs = [("Random",hr),
		  ("RandomK",hk),
		  ("RandomD",hd),
		  ("RandomP", hp)
		  ,("GoT", hg)]

gres = Dict{String,Any}()
#for all graph -> chart
for g in graphs
	runs = 2
	#map serries to x,y,z where x=metav y=metae, z=tss
	data = Dict{String, Serie}()

	data["BinarySearch(H)"]= Serie()
	data["Greedy(H)"]= Serie()
	data["Greedy([H]₂)"]= Serie()
	data["SubTSS(H)"]= Serie()

	pMetaV = range(0.1, stop=0.9, step=0.1)
	pMetaE = range(0.1, stop=0.9, step=0.1)

	for v in pMetaV
		for e in pMetaE
		    results =  @distributed (append!) for run=1:runs
		        metaV = proportionalMetaV(g[2], v)
		        metaE = proportionalMetaE(g[2], e)

		        r1 = greedy_tss_2section(g[2], metaV, metaE)
		        r2 = bisect(g[2],metaV,metaE)
		        r3 = greedy_tss(g[2],metaV,metaE)
				r4 = sub_tss_opt2(g[2],metaV,metaE)

				[(r1,r2,r3,r4[1])]

		    end
			push!(data["Greedy([H]₂)"].x,v)
			push!(data["Greedy([H]₂)"].y,e)
		    push!(data["Greedy([H]₂)"].z,mean([r[1] for r in results]))

			push!(data["BinarySearch(H)"].x,v)
			push!(data["BinarySearch(H)"].y,e)
		    push!(data["BinarySearch(H)"].z,mean([r[2] for r in results]))

			push!(data["Greedy(H)"].x,v)
			push!(data["Greedy(H)"].y,e)
		    push!(data["Greedy(H)"].z,mean([r[3] for r in results]))

			push!(data["SubTSS(H)"].x,v)
			push!(data["SubTSS(H)"].y,e)
		    push!(data["SubTSS(H)"].z,mean([r[4] for r in results]))

		  	println("graph=$(g[1]) meta-v=$v, meta-e=$e")
		end
	end
	push!(gres, g[1]=> data)
	println(data)

end

default(size=(600,600), fc=:heat)
surface(gres["Random"]["Greedy([H]₂)"].x, gres["Random"]["Greedy([H]₂)"].y,  gres["Random"]["Greedy([H]₂)"].z, linealpha = 0.3)
name = "Greedy([H]₂)-Random.png"
Plots.savefig("res/paper/exp3/$name")

surface(data["BinarySearch(H)"].x, data["BinarySearch(H)"].y,  data["BinarySearch(H)"].y, linealpha = 0.3)
name = "BinarySearch(H)-$(g[1]).png"
Plots.savefig("res/paper/exp3/$name")

surface(data["Greedy(H)"].x, data["Greedy(H)"].y,  data["Greedy(H)"].y, linealpha = 0.3)
name = "Greedy(H)-$(g[1]).png"
Plots.savefig("res/paper/exp3/$name")

surface(data["SubTSS(H)"].x, data["SubTSS(H)"].y,  data["SubTSS(H)"].y, linealpha = 0.3)
name = "SubTSS(H)-$(g[1]).png"
Plots.savefig("res/paper/exp3/$name")
#plot data

default(size=(600,600), fc=:heat)
surface(gres["Random"]["BinarySearch(H)"].x, gres["Random"]["BinarySearch(H)"].y,  gres["Random"]["BinarySearch(H)"].z, linealpha = 0.3)
surface(gres["Random"]["Greedy([H]₂)"].x, gres["Random"]["Greedy([H]₂)"].y,  gres["Random"]["Greedy([H]₂)"].z, linealpha = 0.3)

surface(gres["Random"]["Greedy(H)"].x, gres["Random"]["Greedy(H)"].y,  gres["Random"]["Greedy(H)"].z, linealpha = 0.3)
surface(gres["Random"]["SubTSS(H)"].x, gres["Random"]["SubTSS(H)"].y,  gres["Random"]["SubTSS(H)"].z, linealpha = 0.3)


text:
"""
    get_frequency_timers() :: Nothing

Test performance of current frequency implementation for meshes with 30 positive frequencies.
"""
function get_frequency_timers() :: Nothing

    # init test dummys
    list = get_mesh(rand(), 1.0, 30, 0.4)
    m    = Mesh(31, 31, 31, 31, list, list, list, list, list, list)
    w    = rand()
    v    = rand()
    vp   = rand()

    # init timer
    to = TimerOutput()

    # time single interpolation
    @timeit to "=> single interpolation" begin
        for rep in 1 : 10
            @timeit to "-> index search" get_indices(w, list)
            @timeit to "-> param build"  get_param(w, list)
        end
    end

    # time buffer building
    @timeit to "=> buffer building" begin
        for rep in 1 : 10
            @timeit to "-> s channel" get_buffer_s(w, v, vp, m)
            @timeit to "-> t channel" get_buffer_t(w, v, vp, m)
            @timeit to "-> u channel" get_buffer_u(w, v, vp, m)
        end
    end

    show(to)

    return nothing
end


text:
using Plots

include("read_xml.jl")
include("clustering.jl")
include("distances_hour.jl")
include("write_xlsx.jl")
include("write_xml.jl")

# Read client dataset as input
nodes = read_xml("inputs/R101_25.xml")

# Apply clustering algorithm to generate provider nodes
nodes = clusterise(nodes, 3)

# Extract client and provider nodes based on their type
clients = [node for node in nodes if node.type == "client"]
providers = [node for node in nodes if node.type == "provider"]

# Then, generate the corresponding time distance matrix
D_MN = calc_D_MN(providers, clients, 15.0)
D_NN = calc_D_NN(clients, 15.0)

# Write the generated data to XLSX file
write_xlsx("outputs/R101_25.xlsx", providers, clients, D_MN, D_NN)

# Write the generated data (including provider nodes) to XML for VRP-REP mapper
write_xml("outputs/R101_25.xml", nodes, "Solomon 1987 — Set R1", "R101_25")

# Plot generated nodes
cxs = [client.cx for client in clients]
cys = [client.cy for client in clients]
pxs = [provider.cx for provider in providers]
pys = [provider.cy for provider in providers]
plot(pxs, pys, seriestype = :scatter, label="Providers")
plot!(cxs, cys, seriestype = :scatter, label="Clients")

max_stars_repo_name: dwirya/nodegen

max_issues_repo_name: dwirya/nodegen

max_forks_repo_name: dwirya/nodegen


text:
include("ArgLexMin.jl")
include("Dominated.jl")
include("Explore.jl")
include("MakeModel.jl")
include("MinimalT1.jl")
include("MinimalT2.jl")
include("MinMaxModel.jl")
include("MIMMPSolver.jl")
include("DBMIMMPSolver.jl")
include("CBMIMMPSolver.jl")
include("ShaoRSolver.jl")
include("SelectVariable.jl")
include("SelectNode.jl")
include("GLBUpdater.jl")
include("MakeP_bar.jl")
include("VariableType.jl")
include("WeakRemoverModel.jl")
include("Preprocess2.jl")
include("WSM.jl")
include("Vert.jl")
include("FindIntersectingPoint.jl")
include("WeightedMinMaxModel.jl")
include("ConModel.jl")


text:
module ARTON
using ..AGFFileReader: Glass, GlassID, AGF
export F5023, DX4900, D4531F, D4532, D4540, F4520

const F5023 = Glass(GlassID(AGF, 929), 1, 4.4210635, -1.17973758, -1.51543743, 0.513533675, -0.0824061926, 0.00506867714, 0.0, 0.0, 0.0, 0.0, 0.4, 1.6, -0.00025767, -5.7554e-9, 2.4916e-10, 2.0894e-6, -4.8345e-9, 0.0, 23.0, 0.0, -1.0, -1.0, 82.55, -1.0, 0, -1.0, [], 1.512262, -1.0, -1.0, 0, 56.303203, 0, 1.08, 0)
const DX4900 = Glass(GlassID(AGF, 930), 1, 5.07103027, -1.57389549, -1.87102309, 0.618161672, -0.0974376947, 0.00592061276, 0.0, 0.0, 0.0, 0.0, 0.4, 1.6, -0.00024562, -2.7065e-7, 4.789e-10, 3.5474e-6, 3.8368e-8, 0.0, 25.0, 0.0, -1.0, -1.0, 75.0, -1.0, 0, -1.0, [], 1.530803, -1.0, -1.0, 0, 50.654975, 0, 1.08, 0)
const D4531F = Glass(GlassID(AGF, 931), 1, 4.64595347, -1.30462137, -1.65953894, 0.55950693, -0.0894759545, 0.00548941782, 0.0, 0.0, 0.0, 0.0, 0.4, 1.6, -0.00025769, -4.3272e-8, -1.9231e-8, -4.0451e-6, -3.643e-8, 0.0, 23.0, 0.0, -1.0, -1.0, 77.04, -1.0, 0, -1.0, [], 1.514872, -1.0, -1.0, 0, 56.839305, 0, 1.08, 0)
const D4532 = Glass(GlassID(AGF, 932), 1, 4.651451, -1.30962758, -1.66513951, 0.561178589, -0.0897115254, 0.00550194449, 0.0, 0.0, 0.0, 0.0, 0.4, 1.6, -0.00024708, -3.0911e-7, -4.5778e-8, -4.162e-6, 3.8205e-8, 0.0, 23.0, 0.0, -1.0, -1.0, 89.91, -1.0, 0, -1.0, [], 1.513792, -1.0, -1.0, 0, 56.782734, 0, 1.08, 0)
const D4540 = Glass(GlassID(AGF, 933), 1, 4.64595347, -1.30462137, -1.65953894, 0.55950693, -0.0894759545, 0.00548941782, 0.0, 0.0, 0.0, 0.0, 0.4, 1.6, -0.00025769, -4.3272e-8, -1.9231e-8, -4.0451e-6, -3.643e-8, 0.0, 23.0, 0.0, -1.0, -1.0, 74.34, -1.0, 0, -1.0, [], 1.514872, -1.0, -1.0, 0, 56.839305, 0, 1.08, 0)
const F4520 = Glass(GlassID(AGF, 934), 1, 4.4210635, -1.17973758, -1.51543743, 0.513533675, -0.0824061926, 0.00506867714, 0.0, 0.0, 0.0, 0.0, 0.4, 1.6, -0.00025767, -5.7554e-9, 2.49165e-10, 2.08944e-6, -4.83449e-9, 0.0, 23.0, 0.0, -1.0, -1.0, 82.54, -1.0, 0, -1.0, [], 1.512262, -1.0, -1.0, 0, 56.303203, 0, 1.08, 0)
end # module

max_stars_repo_name: rambunctiousapple/GlassCat

max_issues_repo_name: rambunctiousapple/GlassCat

max_forks_repo_name: rambunctiousapple/GlassCat


text:
using HorizonSideRobots

# Инвертировать side
function reverse_side(side::HorizonSide)
    return HorizonSide(mod(Int(side) + 2, 4))
end

# Идти в сторону side, маркируя до упора
function markside(r::Robot, side::HorizonSide)
    while isborder(r, side) == false
        putmarker!(r)
        move!(r, side)
    end
    putmarker!(r)
end

# Идти в сторону side, маркируя до упора, и вернуться к начальному положению
function mark_n_back(r::Robot, side::HorizonSide)
    while isborder(r, side) == false
        move!(r, side)
        putmarker!(r)
    end
    while ismarker(r)==true
        move!(r, HorizonSide(mod(Int(side) + 2, 4))) # В противоположную сторону
    end
end

# Идти в сторону side и вернуть кол-во шагов
function show_path_after_moving(r::Robot, side::HorizonSide)
    n = 0
    while isborder(r, side)==false
        move!(r, side)
        n = n + 1
    end
    return n
end

# Пройти в левый нижний угол и вернуть путь path робота
function go_to_bottom_left_corner_return_path(r::Robot)::Array
    path = []
    while (isborder(r, Sud) == false) || (isborder(r, West) == false)
        if isborder(r, Sud) == false
            move!(r, Sud)
            push!(path, Nord)
        end
        if isborder(r, West) == false
            move!(r, West)
            push!(path, Ost)
        end
    end
    return path
end

# Идти в сторону side n шагов
function move_n(r::Robot, side::HorizonSide, n::Int)
    for i in 1:n
        move!(r, side)
    end
end

# Вернуться в начальное положение по пути path из сторон, при условии, что робот находится в конечной точке маршрута path
function back_by_path_o_sides(r, path::Array)
    n = length(path)
    while n > 0
        move!(r, path[n])
        n = n - 1
    end
end

# Вернуться в начальное положение по пути path, при условии, что робот находится в конечной точке маршрута path
function back_by_path(r::Robot, path::Array)
    k = length(path)
    n = 1 + (k % 2)
    for i in 1:k
        n = n + 1
        side = Nord
        if n % 2 == 1
            side = Ost
        end
        move_n(r, side, path[k - i + 1])
    end
end

# Пройти вперёд, учитывая и проходя через перегородки
function move_through_obstacle(r::Robot, forward_side::HorizonSide)::Bool
    side_side = HorizonSide(mod(Int(forward_side) - 1, 4)) # Направление в сторону обхода
    otherside_side = HorizonSide(mod(Int(side_side) + 2, 4)) # Обратное направление в сторону
    n = 0
    if isborder(r,forward_side)==false
        move!(r,forward_side)
        not_hit_border=true
    else
        while isborder(r,forward_side) == true
            if isborder(r, side_side) == false
                move!(r, side_side)
                n += 1
            else
                break
            end
        end
        if isborder(r,forward_side) == false
            move!(r,forward_side)
            while isborder(r, otherside_side) == true
                move!(r,forward_side)
            end
            not_hit_border = true
        else
            not_hit_border = false
        end
        while n > 0
            n -= 1
            move!(r, otherside_side)
        end
    end
    return not_hit_border
end


text:
using SymbolServer, Pkg
using SymbolServer: packagename, packageuuid, deps, manifest, project, version, Package, frommanifest
using Base:UUID
using Test

@testset "SymbolServer" begin
    server = SymbolServerProcess()

    @test server isa SymbolServerProcess
    @test server.context isa Pkg.Types.Context
    SymbolServer.get_context(server)
    @test server.context isa Pkg.Types.Context
    @test "SymbolServer" in keys(deps(project(server.context)))
    @test SymbolServer.isinproject(server.context, "SymbolServer")
    @test SymbolServer.isinmanifest(server.context, "SymbolServer")

    @test all(d in keys(deps(project(server.context))) for d in ("LibGit2", "Pkg", "SHA", "Serialization"))

    uuid = packageuuid(server.context, "SymbolServer")
    @test uuid isa UUID

    pe = frommanifest(server.context, uuid)
    @test pe isa SymbolServer.PackageEntry

    @test !isempty(server.depot["Base"].vals)
    @test !isempty(server.depot["Core"].vals)

    @testset "Cache package on client side" begin
        depot = Dict{UUID,Package}()
        ss_m = SymbolServer.cache_package(server.context, uuid, depot)
        @test any(p->p[2].name == "SymbolServer", depot)
        @test any(p->p[2].name == "Pkg", depot)
        @test any(p->p[2].name == "SHA", depot)
    end

    @testset "Cache package on server side" begin
        uuid = packageuuid(server.context, "SHA")
        SymbolServer.cache_package(server, uuid)
        SymbolServer.update(server)
        @test "SHA" in keys(server.depot)
    end

    @testset "Load manifest packages" begin
        SymbolServer.load_manifest_packages(server)
        kill(server)
    end

    @testset "Load project packages" begin
        server = SymbolServerProcess()
        SymbolServer.load_project_packages(server)
        @test all(k in keys(server.depot) for k in ("LibGit2", "Pkg", "SHA", "Serialization"))
        kill(server)
    end
end


text:
export rule

@rule Beta(:out, Marginalisation) (m_a::PointMass, m_b::PointMass) = Beta(mean(m_a), mean(m_b))

@rule Beta(:out, Marginalisation) (q_a::PointMass, q_b::PointMass) = Beta(mean(q_a), mean(q_b))


text:
module CSVReader

using DataFrames: DataFrame, AbstractDataFrame, nrow
using InternedStrings: intern
using Parsers: tryparse

export @parsers_str

# This is twice as fast as the regular strip() function
faststrip(x, quotechar) = length(x) > 2 ? (x[1] == x[end] == quotechar ? x[2:end-1] : x) : x

# Parsers
parse_string(s) = intern(s)
parser_return_type(::Val{parse_string}) = Union{String, Missing}

parse_float64(s) = something(tryparse(Float64, s), missing)
parser_return_type(::Val{parse_float64}) = Union{Float64, Missing}

parse_int(s) = something(tryparse(Int, s), missing)
parser_return_type(::Val{parse_int}) = Union{Int, Missing}

"""
Construct parsers from a parser spec string.  The string contains a
comman separated value of the format <parser>:<length>.  For example,
s:10,f:2,i:5 means 10 strings, 2 floats, and 5 int's.
"""
macro parsers_str(s)
    parser_dict = Dict("i" => parse_int, "f" => parse_float64, "s" => parse_string)
    parsers = []
    sep = ":"
    for spec ∈ split(s, ",")
        if occursin(sep, spec)
            T, L = split(spec, sep)     # f:10 => means 10 floats
            N = tryparse(Int, L)
            !haskey(parser_dict, T) && error("Invalid parser spec: $spec (unknown parser '$T')")
            (N == nothing || N <= 0) && error("Invalid parser spec: $spec (bad length '$N')")
            parsers = vcat(parsers, fill(parser_dict[T], N))
        else
            T = spec
            !haskey(parser_dict, T) && error("Invalid parser spec: $spec (unknown parser)")
            push!(parsers, parser_dict[T])
        end
    end
    parsers
end

"""
    Read CSV file

Read a CSV formatted file as specified by `filename`.  If `parsers` is not specified
then it is inferred from the first line.  Use `headers` keyword parameter to control
whether a header line is present for column names.
"""
# DataFrame approach but have a parsing state machine
function read_csv(filename, parsers = nothing;
                    headers = true,
                    delimiter = ',',
                    quotechar = '"')
    parsers = something(parsers, infer_parsers(filename, headers, delimiter, quotechar))
    est_lines = estimate_lines_in_file(filename, with_headers = headers)
    open(filename) do f
        hdr = read_headers(f, headers, delimiter, quotechar)
        r = 0
        preallocate_rows = est_lines
        df = make_dataframe(hdr, parser_return_type.(Val.(parsers)), preallocate_rows)
        @inbounds while !eof(f)
            line = readline(f)
            r += 1
            if r > preallocate_rows
                new_size = max(floor(Int, preallocate_rows * 1.05 + 5), preallocate_rows + 5)
                @debug "Growing data frame from $preallocate_rows rows to $new_size"
                grow_dataframe!(df, new_size)
                preallocate_rows = new_size
            end
            # This state machine keeps track of two indices (i,j).
            # The value of `j` is incremented until it hits a delimiter or end of string.
            # The value of `k` is then determined as `j-1` if line[j] is a delimiter,
            # else `k` would have the same index as `end` of line.
            # The cell is then consumed i.e. stripped, parsed, and set.
            # Reference: i = start, j = pointer, k = end, c = column index
            len = length(line)
            i = j = c = 1
            within_quote = false
            while i <= len && j <= len
                if line[j] == quotechar
                    within_quote = !within_quote
                end
                if (!within_quote && line[j] == delimiter) || j == len
                    k = (j == len) ? len : j-1  # special case at end of line
                    df[r, c] = faststrip(line[i:k], quotechar) |> parsers[c]
                    c += 1
                    i = j = j+1
                else
                    j += 1
                end
            end
            # parse_line!(df, r, parsers, line, delimiter, quotechar)
        end
        trim_table(df, r)
    end
end

"""
Peek into first few lines of CSV file
"""
function peek_csv(filename; headers = true, nrows = 5, delimiter = ',', quotechar = '"')
    open(filename) do f
        headers = read_headers(f, headers, delimiter, quotechar)
        rows = read_first_few_lines(f, nrows)
        column_names = [split(row, delimiter) for row ∈ rows]
        ncols = maximum(length(x) for x ∈ column_names)
        @info "Peeking into first few rows => there are $ncols columns" rows
    end
    nothing
end

# Warning: type piracy!
function grow_dataframe!(df::AbstractDataFrame, rows::Integer)
    rows <= nrow(df) && error("Current data frame has $(nrow(df)) rows but you specified to grow to $rows rows!")
    for c ∈ names(df)
        df[c] = resize!(df[c], rows)
    end
    nothing
end

function parse_line!(df, row, parsers, line, delimiter, quotechar)
    strings = split(line, delimiter)
    for (i, parser) ∈ enumerate(parsers)
        parsed_value = faststrip(strings[i], quotechar) |> parser
        #@debug "Parsed line" row i parsed_value
        df[row,i] = parsed_value
    end
    nothing
end

# Make a new DataFrame
function make_dataframe(hdr, types, rows)
    # @info "Making table with $rows rows"
    # @info "Types = $types"
    # @info "Types[11] = $(types[11])"
    hdr = something(hdr, ["_$i" for i ∈ 1:length(types)])
    cols = [Vector{T}(undef, rows) for T ∈ types]
    df = DataFrame(cols, Symbol.(hdr), makeunique = true)
    df
end

function trim_table(df, rows)
    @debug "Trimming table" nrow(df) rows
    df[1:rows, :]
end

function read_headers(f, headers, delimiter, quotechar)
    if headers
        map(h -> faststrip(h, quotechar), split(readline(f), delimiter))
    else
        nothing
    end
end

function infer_parsers(filename, headers, delimiter, quotechar)
    open(filename) do f
        headers && readline(f)
        first_line = readline(f)
        cells = map(x -> faststrip(x, quotechar), split(first_line, delimiter))
        infer_parser.(cells)
    end
end

# infer parser needed from a string
function infer_parser(s)
    if match(r"^-?\d+\.\d*$", s) != nothing ||      # covers 12.
            match(r"^-?\d*\.\d+$", s)!= nothing ||  # covers .12
            match(r"^-?\d+\.\d*e[+-]\d$", s) != nothing
        parse_float64
    elseif match(r"^-?\d+$", s) != nothing          # covers 123
        parse_int
    else
        parse_string
    end
end

# get some sample lines
function get_sample_lines(filename; headers = true, max_reach_pct = 0.1, samples_pct = 0.1, max_samples = 10)
    L = estimate_lines_in_file(filename)
    L_upper = floor(Int, L * max_reach_pct)   # don't read lines further than this
    L_lower = headers ? 2 : 1
    num_samples = min(max_samples, floor(Int, L_upper * samples_pct))
    @info "There are approximately $L lines in the file"
    @info "Taking at most $(num_samples) samples between L$(L_lower) and L$(L_upper)"
    samples = unique(sort(rand(L_lower:L_upper, num_samples)))
    n = 1
    i = 1
    lines = String[]
    open(filename) do f
        while !eof(f)
            line = readline(f)
            if n == samples[i]   # take sample
                push!(lines, line)
                i += 1
                i > length(samples) && break
            end
            n += 1
        end
    end
    lines
end

function estimate_lines_in_file(filename; line_length_samples = 10, with_headers = true)
    s = filesize(filename)
    open(filename) do f
        with_headers && readline(f)  # skip header
        L =  estimate_line_length(f, line_length_samples)
        L > 0 ? s ÷ L : 0
    end
end

function estimate_line_length(f, line_length_samples)
    few_lines = read_first_few_lines(f, line_length_samples)
    if length(few_lines) > 0
        sum(length, few_lines) ÷ length(few_lines)
    else
        0
    end
end

function read_first_few_lines(f, lines_to_read)
    lines = String[]
    count = 0
    while !eof(f) && count < lines_to_read
        line = readline(f)
        push!(lines, line)
        count += 1
    end
    lines
end

# -------------------
# Experimental stuffs
# -------------------

# Return vector of named tuples
function read_csv_nt(filename, parsers = nothing;
                        headers = true,
                        delimiter = ',',
                        quotechar = '"')
    parsers = something(parsers, infer_parsers(filename, headers, delimiter, quotechar))
    result = Vector{NamedTuple}()
    open(filename) do f
        # header symbols
        hdr = read_headers(f, headers, delimiter, quotechar)
        hdr = something(hdr, ["_$i" for i ∈ 1:length(parsers)])
        hdr = Tuple(Symbol.(hdr))
        ncol = length(parsers)
        r = 0
        v = Any[nothing for _ in 1:ncol]
        T = NamedTuple{hdr}
        while !eof(f)
            line = readline(f)
            r += 1
            s = split(line, delimiter)
            @inbounds for i in 1:ncol
                v[i] = faststrip(s[i], quotechar) |> parsers[i]
            end
            push!(result, T(v))
        end
    end
    result
end

# Return vector of named tuples but also have a parsing state machine
function read_csv_nt2(filename, parsers = nothing;
                    headers = true,
                    delimiter = ',',
                    quotechar = '"')
    parsers = something(parsers, infer_parsers(filename, headers, delimiter, quotechar))
    open(filename) do f
        # header symbols
        hdr = read_headers(f, headers, delimiter, quotechar)
        hdr = something(hdr, ["_$i" for i ∈ 1:length(parsers)])
        hdr = Tuple(Symbol.(hdr))
        ncol = length(parsers)
        r = 0
        v = Any[nothing for _ in 1:ncol]
        T = NamedTuple{hdr}
        result = Vector{T}()
        while !eof(f)
            line = readline(f)
            len = length(line)
            i = j = c = 1
            while i <= len && j <= len
                if line[j] == delimiter || j == len
                    k = (j == len) ? len : j-1  # special case at end of line
                    v[c] = faststrip(line[i:k], quotechar) |> parsers[c]
                    c += 1
                    i = j = j+1
                else
                    j += 1
                end
            end
            push!(result, T(v))
        end
        result
    end
end

end # module


text:
module BoardGames

#using...

export
    # Abstract types
    Game,
    Strategy,

    # game functions
    boardtype,
    movetype,
    play,
    play!,
    getmoves,
    initialboard,
    playerturn,
    winner,
    nplayers,

    # strategy functions
    getmove,
    playgame,
    name,
    getvarsnames,
    getvalues,
    setvalue!

include("game.jl")
include("strategy.jl")

# Write your package code here.

end


text:
#=
This file is part of Pseudospectra.jl.

Julia translation
copyright (c) 2017 Ralph Smith

Portions derived from EigTool
Copyright (c) 2002-2014, The Chancellor, Masters and Scholars
of the University of Oxford, and the EigTool Developers. All rights reserved.

SPDX-License-Identifier: BSD-3-Clause
License-Filename: LICENSES/BSD-3-Clause_Eigtool
=#

"""
    zoomin!(ps_data,z,ax) -> Int

update `ps_data` to include a finer resolution portrait.

Returns -1 for invalidity, 0 for return to an existing zoom (requiring
a redraw), and 1 for establishment of new one (requiring a recalculation
and redraw).
"""
function zoomin!(ps_data::PSAStruct,z,ax)
    zr,zi = real(z[1]),imag(z[1])
    if ((zr < ax[1]) || (zr > ax[2]) || (zi < ax[3]) || (zi > ax[4]))
        return -1
    end
    zoom = ps_data.zoom_list[ps_data.zoom_pos]
    if length(z) == 1
        zr2,zi2 = zr,zi
    else
        zr2,zi2 = real(z[2]),imag(z[2])
    end
    zax = zoom.ax
    final_rect = [max(zax[1],min(zr,zr2)),min(zax[2],max(zr,zr2)),
                  max(zax[3],min(zi,zi2)),min(zax[4],max(zi,zi2))]
    aw = ax[2] - ax[1]
    ah = ax[4] - ax[3]
    # if rectangle is trivial, zoom in on first point, mag factor 2
    if (abs(final_rect[2]-final_rect[1])/aw < 0.01) ||
        (abs(final_rect[4]-final_rect[3])/ah < 0.01)
        # if at end of zoom chain, append
        if ps_data.zoom_pos == length(ps_data.zoom_list)
            w = zax[2]-zax[1]
            h = zax[4]-zax[3]
            # start with a copy of current portrait
            push!(ps_data.zoom_list,deepcopy(zoom))
            ps_data.zoom_pos += 1
            newzoom = ps_data.zoom_list[ps_data.zoom_pos]
            # work out new axes
            newax = [final_rect[1]-w/4,final_rect[1]+w/4,
                     final_rect[3]-h/4,final_rect[3]+h/4]
            copyto!(newzoom.ax,newax)
            final_rect = newzoom.ax # note: an alias

            # for real matrix, if box is almost up-down symmetric,
            # enforce symmetry
            if ps_data.ps_dict[:Aisreal]
                span = final_rect[4] - final_rect[3]
                the_diff = (final_rect[4] + final_rect[3])/span
                if abs(the_diff) < 0.15
                    final_rect[3] = -maximum(abs.(final_rect[3:4]))
                    final_rect[4] = maximum(abs.(final_rect[3:4]))
                end
            end
            ax1 = newzoom.ax
            ax1[1],ax1[2] = tidyaxes(ax1[1],ax1[2],0.05)
            ax1[3],ax1[4] = tidyaxes(ax1[3],ax1[4],0.05)
            retval = 1
        else # there is already a zoom to go to
            ps_data.zoom_pos += 1
            retval = 0
        end
    else # nontrivial rectangle branch
        # start with a copy of current zoom
        push!(ps_data.zoom_list,deepcopy(zoom))
        ps_data.zoom_pos += 1
        # drop any obsolete zooms
        resize!(ps_data.zoom_list,ps_data.zoom_pos)
        newzoom = ps_data.zoom_list[ps_data.zoom_pos]
        # for real matrix, if box is almost up-down symmetric, enforce symmetry
        if ps_data.ps_dict[:Aisreal]
            span = final_rect[4] - final_rect[3]
            the_diff = (final_rect[4] + final_rect[3])/span
            if abs(the_diff) < 0.15
                final_rect[3] = -maximum(abs.(final_rect[3:4]))
                final_rect[4] = maximum(abs.(final_rect[3:4]))
            end
        end
        copy!(newzoom.ax,final_rect)
        ax1 = newzoom.ax
        ax1[1],ax1[2] = tidyaxes(ax1[1],ax1[2],0.02)
        ax1[3],ax1[4] = tidyaxes(ax1[3],ax1[4],0.02)
        newzoom.computed = false
        retval = 1
    end
    retval
end

"""
    zoomout!(ps_data,z,ax) -> Int

update `ps_data` to include a coarser resolution portrait.

Returns -1 for invalidity, 0 for return to an existing zoom (requiring
a redraw), and 1 for establishment of new one (requiring a recalculation
and redraw).
"""
function zoomout!(ps_data::PSAStruct,z,ax; include_fov=false)
    zr,zi = real(z[1]),imag(z[1])
    if (zr < ax[1]) || (zr > ax[2]) || (zi < ax[3]) || (zi > ax[4])
        return -1
    end
    if ps_data.zoom_pos > 1
        # restore previous zoom level
        ps_data.zoom_pos -= 1
        retval = 0
    else # no previous zoom entry to use; zoom out by factor of 2
        newzoom = deepcopy(ps_data.zoom_list[1])
        newzoom.computed = false
        pushfirst!(ps_data.zoom_list, newzoom)
        zax = newzoom.ax
        ps_dict = ps_data.ps_dict
        if include_fov && !isempty(get(ps_dict,:fov,zeros(0))) &&
              get(ps_dict,:show_fov,false)
            mnr,mxr = extrema(real(ps_dict[:fov]))
            mni,mxi = extrema(imag(ps_dict[:fov]))
            zoom2fov = (mnr <= zax[1]) || (mxr >= zax[2]) || (mni <= zax[3]) ||
                (mxi >= zax[4])
        else
            zoom2fov = false
        end
        if zoom2fov
            w = mxr - mnr
            h = mxi - mni
            ps_data.zoom_pos = 1
            zax[1] = mnr - w/4
            zax[2] = mxr + w/4
            zax[3] = mni - h/4
            zax[4] = mxi + h/4
        else
            # grow around selected point
            w = zax[2] - zax[1]
            h = zax[4] - zax[3]
            ps_data.zoom_pos = 1
            zax[1] = zr - w
            zax[2] = zr + w
            zax[3] = zi - h
            zax[4] = zi + h
        end
        zax[1],zax[2] = tidyaxes(zax[1],zax[2],0.05)
        zax[3],zax[4] = tidyaxes(zax[3],zax[4],0.05)
        retval = 1
    end
    retval
end


text:
function addnotfound(message::String,myendpoints::Dict{Int64,Array{NamedTuple{(:route, :toexec, :urlparams),Tuple{Union{String,Regex},Function,Union{Nothing,Dict{Int64,String}}}},1}})
  myendpoints[0] = [(route= "", toexec= function nf(request,HTTP); return HTTP.Response(404,message); end, urlparams= nothing)]
end

function createurlparams(url::String)::Dict{Int64,String}
	params = Dict{Int64,String}()

    for (index, value) in enumerate(split(url,"/"))
    	if(length(value)>1 )
    		if (value[1] ==':')
               params[index] = value[2:end]
    		end
    		if (value[1] =='(')
    			params[index] = string(index)
    		end
    	end
    end

    return params
end

function convertregex(url::String)::Regex

	if occursin(":",url)
		url = replace(url, r":(\w+)" => s"\\w+")
	end

	return Regex(string("^",url,"\$"))
end

function createurl(method::String,url::String,functiontoexec::Function,myendpoints::Dict{Int64,Array{NamedTuple{(:route, :toexec, :urlparams),Tuple{Union{String,Regex},Function,Union{Nothing,Dict{Int64,String}}}},1}},tonumber::Dict{String,Char},cleanurl::Function,createurlparams::Function,convertregex::Function)::Nothing

	nvalues::Int64 = 0
	myurlparams::Union{Nothing,Dict{Int64,String}} = nothing
	mycleanurl::Union{String,Regex} = cleanurl(url)

	if(length(url)>1)
		nvalues = length(split(mycleanurl,"/"))
	end

    if occursin(":",mycleanurl) || occursin("(",mycleanurl)
      myurlparams = createurlparams(mycleanurl)
      mycleanurl = convertregex(mycleanurl)
    end

	myroute::NamedTuple{(:route, :toexec, :urlparams),Tuple{Union{String,Regex},Function,Union{Nothing,Dict{Int64,String}}}} = (route= mycleanurl, toexec= functiontoexec,  urlparams = myurlparams )
	indexsearch::Int64 = parse(Int64, string(tonumber[method] , nvalues))

    if haskey(myendpoints, indexsearch)
    	push!(myendpoints[indexsearch], myroute )
    else
        myendpoints[indexsearch] = [myroute]
    end

    @info(string(method," > ",url))

end

macro page(exp1::String,exp2::Union{String,Expr})
	quote
    createurl("GET",$exp1,((request,HTTP)->$exp2 ),myendpoints,tonumber,cleanurl,createurlparams,convertregex)
    CorsOptions($exp1)
    end
end

macro page(exp1::String, exp2::Expr ,exp3::Expr)
    parameters = repr(exp2)[3:end-1]
    quote
    createurl("GET",$exp1,( $(Meta.parse(string("myfunction", parameters))) = (request,HTTP)->$exp3 )(),myendpoints,tonumber,cleanurl,createurlparams,convertregex)
    CorsOptions($exp1)
    end
end

macro route(exp1,exp2::String,exp3::Expr)
  quote
    for i in split($exp1,"|")
      createurl(String(i),$exp2,((request,HTTP)->$exp3),myendpoints,tonumber,cleanurl,createurlparams,convertregex)
      if(String(i) != "OPTIONS")
        CorsOptions($exp2)
      end
    end
  end
end

macro route(exp1,exp2::String,exp3::Expr, exp4::Expr)
  parameters = repr(exp3)[3:end-1]
  quote
    for i in split($exp1,"|")
      createurl(String(i),$exp2,( $(Meta.parse(string("myfunction", parameters))) = (request,HTTP)->$exp4 )(),myendpoints,tonumber,cleanurl,createurlparams,convertregex)
      if(String(i) != "OPTIONS")
        CorsOptions($exp2)
      end
    end
  end
end

function Get(URL::String, fun::Function)::Nothing
  createurl("GET",URL,fun,myendpoints,tonumber,cleanurl,createurlparams,convertregex)
  CorsOptions(URL)
end

function Post(URL::String, fun::Function)::Nothing
  createurl("POST",URL,fun,myendpoints,tonumber,cleanurl,createurlparams,convertregex)
  CorsOptions(URL)
end

function Put(URL::String, fun::Function)::Nothing
  createurl("PUT",URL,fun,myendpoints,tonumber,cleanurl,createurlparams,convertregex)
  CorsOptions(URL)
end

function Delete(URL::String, fun::Function)::Nothing
  createurl("DELETE",URL,fun,myendpoints,tonumber,cleanurl,createurlparams,convertregex)
  CorsOptions(URL)
end

function Connect(URL::String, fun::Function)::Nothing
  createurl("CONNECT",URL,fun,myendpoints,tonumber,cleanurl,createurlparams,convertregex)
end

function Trace(URL::String, fun::Function)::Nothing
  createurl("TRACE",URL,fun,myendpoints,tonumber,cleanurl,createurlparams,convertregex)
end

function Head(URL::String, fun::Function)::Nothing
  createurl("HEAD",URL,fun,myendpoints,tonumber,cleanurl,createurlparams,convertregex)
  CorsOptions(URL)
end

function Options(URL::String, fun::Function)::Nothing
  createurl("OPTIONS",URL,fun,myendpoints,tonumber,cleanurl,createurlparams,convertregex)
end

function Patch(URL::String, fun::Function)::Nothing
  createurl("PATCH",URL,fun,myendpoints,tonumber,cleanurl,createurlparams,convertregex)
end

function CorsOptions(URL::String)::Nothing
  if (CORSenabled[1] !== nothing)
      Options(URL,CORSenabled[1])
  end
end


text:
int main() {
  1; // this should be a void expression
  return 1;
}

max_stars_repo_name: fredefox/javalette

max_issues_repo_name: fredefox/javalette

max_forks_repo_name: fredefox/javalette


text:
using Bijectors:
    Coupling,
    PartitionMask,
    coupling,
    couple,
    partition,
    combine,
    Shift,
    Scale

@testset "Coupling" begin
    @testset "PartitionMask" begin
        m1 = PartitionMask(3, [1], [2])
        m2 = PartitionMask(3, [1], [2], [3])

        @test (m1.A_1 == m2.A_1) & (m1.A_2 == m2.A_2) & (m1.A_3 == m2.A_3)

        x = [1., 2., 3.]
        x1, x2, x3 = partition(m1, x)
        @test (x1 == [1.]) & (x2 == [2.]) & (x3 == [3.])

        y = combine(m1, x1, x2, x3)
        @test y == x
    end

    @testset "Basics" begin
        m = PartitionMask(3, [1], [2])
        cl1 = Coupling(x -> Shift(x[1]), m)

        x = [1., 2., 3.]
        @test cl1(x) == [3., 2., 3.]

        cl2 = Coupling(θ -> Shift(θ[1]), m)
        @test cl2(x) == cl1(x)

        # inversion
        icl1 = inv(cl1)
        @test icl1(cl1(x)) == x
        @test inv(cl2)(cl2(x)) == x

        # This `cl2` should result in
        b = Shift(x[2:2])

        # logabsdetjac
        @test logabsdetjac(cl1, x) == logabsdetjac(b, x[1:1])

        # forward
        @test forward(cl1, x) == (rv = cl1(x), logabsdetjac = logabsdetjac(cl1, x))
        @test forward(icl1, cl1(x)) == (rv = x, logabsdetjac = - logabsdetjac(cl1, x))
    end

    @testset "Classic" begin
        m = PartitionMask(3, [1], [2])

        # With `Scale`
        cl = Coupling(x -> Scale(x[1]), m)
        x = hcat([-1., -2., -3.], [1., 2., 3.])
        y = hcat([2., -2., -3.], [2., 2., 3.])
        test_bijector(cl, x, y, log.([2., 2.]))
    end
end


text:
"An asynchronous PostgreSQL query"
mutable struct AsyncResult{BinaryFormat}
    "The LibPQ.jl Connection used for the query"
    jl_conn::Connection

    "Keyword arguments to pass to Result on creation"
    result_kwargs::Ref

    "Whether or not the query should be cancelled, if running"
    should_cancel::Bool

    "Task which errors or returns a LibPQ.jl Result which is created once available"
    result_task::Task

    function AsyncResult{BinaryFormat}(
        jl_conn::Connection, result_kwargs::Ref
    ) where BinaryFormat
        return new{BinaryFormat}(jl_conn, result_kwargs, false)
    end
end

function AsyncResult{BinaryFormat}(jl_conn::Connection; kwargs...) where BinaryFormat
    return AsyncResult{BinaryFormat}(jl_conn, Ref(kwargs))
end

function Base.show(io::IO, async_result::AsyncResult)
    status = if isready(async_result)
        if iserror(async_result)
            "errored"
        else
            "finished"
        end
    else
        "in progress"
    end
    return print(io, typeof(async_result), " (", status, ")")
end

"""
    handle_result(async_result::AsyncResult; throw_error=true) -> Result

Executes the query in `async_result` and waits for results.

This implements the loop described in the PostgreSQL documentation for
[Asynchronous Command Processing](https://www.postgresql.org/docs/10/libpq-async.html).

The `throw_error` option only determines whether to throw errors when handling the new
[`Result`](@ref)s; the `Task` may error for other reasons related to processing the
asynchronous loop.

The result returned will be the [`Result`](@ref) of the last query run (the only query if
using parameters).
Any errors produced by the queries will be thrown together in a `CompositeException`.
"""
function handle_result(
    async_result::AsyncResult{BinaryFormat}; throw_error=true
) where BinaryFormat
    errors = []
    result = nothing
    for result_ptr in _consume(async_result.jl_conn)
        try
            result = handle_result(
                Result{BinaryFormat}(
                    result_ptr, async_result.jl_conn; async_result.result_kwargs[]...
                );
                throw_error=throw_error,
            )
        catch err
            push!(errors, err)
        end
    end

    if throw_error && !isempty(errors)
        throw(CompositeException(errors))
    elseif result === nothing
        error(LOGGER, Errors.JLResultError("Async query did not return result"))
    else
        return result
    end
end

function _consume(jl_conn::Connection)
    # libpq does this to "give the data a push" and I don't know what that means but maybe
    # this is important?
    # https://github.com/postgres/postgres/blob/master/src/interfaces/libpq/fe-exec.c#L1266
    # if we used non-blocking connections we would need to check for `1` as well
    if libpq_c.PQflush(jl_conn.conn) < 0
        error(LOGGER, Errors.PQConnectionError(jl_conn))
    end

    async_result = jl_conn.async_result
    result_ptrs = Ptr{libpq_c.PGresult}[]
    watcher = FDWatcher(socket(jl_conn), true, false)  # can wait for reads
    try
        # Wait at least 5 seconds between emitting wait or consume log messages
        last_log = time()

        while true
            curr = time()
            last_log = curr - last_log > 5.0 ? curr : last_log

            if async_result.should_cancel
                debug(LOGGER, "Received cancel signal for connection $(jl_conn.conn)")
                _cancel(jl_conn)
            end

            last_log == curr &&
                debug(LOGGER, "Waiting to read from connection $(jl_conn.conn)")
            wait(watcher)
            last_log == curr &&
                debug(LOGGER, "Consuming input from connection $(jl_conn.conn)")
            success = libpq_c.PQconsumeInput(jl_conn.conn) == 1
            !success && error(LOGGER, Errors.PQConnectionError(jl_conn))

            while libpq_c.PQisBusy(jl_conn.conn) == 0
                debug(LOGGER, "Checking the result from connection $(jl_conn.conn)")
                result_ptr = libpq_c.PQgetResult(jl_conn.conn)
                if result_ptr == C_NULL
                    debug(LOGGER, "Finished reading from connection $(jl_conn.conn)")
                    return result_ptrs
                else
                    result_num = length(result_ptrs) + 1
                    debug(
                        LOGGER, "Saving result $result_num from connection $(jl_conn.conn)"
                    )
                    push!(result_ptrs, result_ptr)
                end
            end
        end
    catch err
        if err isa Base.IOError && err.code == -9  # EBADF
            debug(() -> sprint(showerror, err), LOGGER)
            error(
                LOGGER,
                Errors.JLConnectionError(
                    "PostgreSQL connection socket was unexpectedly closed"
                ),
            )
        else
            rethrow(err)
        end
    finally
        close(watcher)
    end
end

"""
    cancel(async_result::AsyncResult)

If this [`AsyncResult`](@ref) represents a currently-executing query, attempt to cancel it.
"""
function cancel(async_result::AsyncResult)
    # just sets the `should_cancel` flag
    # the actual cancellation will be triggered in the main loop of _consume
    # which will call `_cancel` on the `Connection`
    async_result.should_cancel = true
    return nothing
end

function _cancel(jl_conn::Connection)
    cancel_ptr = libpq_c.PQgetCancel(jl_conn.conn)
    try
        # https://www.postgresql.org/docs/10/libpq-cancel.html#LIBPQ-PQCANCEL
        errbuf_size = 256
        errbuf = zeros(UInt8, errbuf_size)
        success = libpq_c.PQcancel(cancel_ptr, pointer(errbuf), errbuf_size) == 1
        if !success
            warn(
                LOGGER,
                Errors.JLConnectionError("Failed cancelling query: $(String(errbuf))"),
            )
        else
            debug(LOGGER, "Cancelled query for connection $(jl_conn.conn)")
        end
    finally
        libpq_c.PQfreeCancel(cancel_ptr)
    end
end

iserror(async_result::AsyncResult) = Base.istaskfailed(async_result.result_task)
Base.isready(async_result::AsyncResult) = istaskdone(async_result.result_task)
Base.wait(async_result::AsyncResult) = wait(async_result.result_task)
Base.fetch(async_result::AsyncResult) = fetch(async_result.result_task)
Base.close(async_result::AsyncResult) = cancel(async_result)

"""
    async_execute(
        jl_conn::Connection,
        query::AbstractString,
        [parameters::Union{AbstractVector, Tuple},]
        binary_format::Bool=false,
        kwargs...
    ) -> AsyncResult

Run a query on the PostgreSQL database and return an [`AsyncResult`](@ref).

The `AsyncResult` contains a `Task` which processes a query asynchronously.
Calling `fetch` on the `AsyncResult` will return a [`Result`](@ref).

All keyword arguments are the same as [`execute`](@ref) and are passed to the created
`Result`.

Only one `AsyncResult` can be active on a [`Connection`](@ref) at once.
If multiple `AsyncResult`s use the same `Connection`, they will execute serially.

`async_execute` does not yet support [`Statement`](@ref)s.

`async_execute` optionally takes a `parameters` vector which passes query parameters as
strings to PostgreSQL.

`binary_format`, when set to true, will transfer the data in binary format.
Support for binary transfer is currently limited to a subset of basic data types.

Queries without parameters can contain multiple SQL statements, and the result of the final
statement is returned.
Any errors which occur during executed statements will be bundled together in a
`CompositeException` and thrown.

As is normal for `Task`s, any exceptions will be thrown when calling `wait` or `fetch`.
"""
function async_execute end

function async_execute(conn, query; binary_format=false, kwargs...)
    if binary_format
        async_execute(conn, query, []; binary_format=binary_format, kwargs...)
    else
        _multi_async_execute(conn, query; kwargs...)
    end
end

function _multi_async_execute(jl_conn::Connection, query::AbstractString; kwargs...)
    async_result = _async_execute(jl_conn; kwargs...) do jl_conn
        _async_submit(jl_conn.conn, query)
    end

    return async_result
end

function async_execute(
    jl_conn::Connection,
    query::AbstractString,
    parameters::Union{AbstractVector,Tuple};
    binary_format::Bool=false,
    kwargs...,
)
    string_params = string_parameters(parameters)
    pointer_params = parameter_pointers(string_params)

    async_result = _async_execute(jl_conn; binary_format=binary_format, kwargs...) do jl_conn
            _async_submit(jl_conn.conn, query, pointer_params; binary_format=binary_format)
        end

    return async_result
end

function _async_execute(
    submission_fn::Function,
    jl_conn::Connection;
    binary_format::Bool=false,
    throw_error::Bool=true,
    kwargs...,
)
    async_result = AsyncResult{binary_format}(jl_conn; kwargs...)

    async_result.result_task = @async lock(jl_conn) do
        jl_conn.async_result = async_result

        try
            # error if submission fails
            # does not respect `throw_error` as there's no result to return on this error
            if !submission_fn(jl_conn)
                error(LOGGER, Errors.PQConnectionError(async_result.jl_conn))
            end

            return handle_result(async_result; throw_error=throw_error)::Result
        finally
            jl_conn.async_result = nothing
        end
    end

    return async_result
end

function _async_submit(conn_ptr::Ptr{libpq_c.PGconn}, query::AbstractString)
    return libpq_c.PQsendQuery(conn_ptr, query) == 1
end

function _async_submit(
    conn_ptr::Ptr{libpq_c.PGconn},
    query::AbstractString,
    parameters::Vector{Ptr{UInt8}};
    binary_format::Bool=false,
)
    num_params = length(parameters)

    send_status = libpq_c.PQsendQueryParams(
        conn_ptr,
        query,
        num_params,
        C_NULL,  # set paramTypes to C_NULL to have the server infer a type
        parameters,
        C_NULL,  # paramLengths is ignored for text format parameters
        zeros(Cint, num_params),  # all parameters in text format
        Cint(binary_format),  # return result in text or binary format
    )

    return send_status == 1
end


text:
# TODO σ_mm=5

# MCPC-3D-S is implemented for both complex and phase + magnitude data to allow
# working with large mmaped files from disk

# Functions for convenient calling
mcpc3ds(phase::AbstractArray{<:Real}; keyargs...) = angle.(mcpc3ds(exp.(1im .* phase); keyargs...))
mcpc3ds(phase, mag; keyargs...) = mcpc3ds(PhaseMag(phase, mag); keyargs...)
# MCPC3Ds in complex (or PhaseMag)
function mcpc3ds(image; TEs, echoes=[1,2], σ=[10,10,5],
        bipolar_correction=false,
        po=zeros(Float64,(size(image)[1:3]..., size(image,5)))
    )
    ΔTE = TEs[echoes[2]] - TEs[echoes[1]]
    hip = getHIP(image; echoes) # complex
    weight = sqrt.(abs.(hip))
    mask = robustmask(weight)
    # TODO try to include additional second-phase information in the case of 3+ echoes for ROMEO, maybe phase2=phase[3]-phase[2], TEs=[dTE21, dTE32]
    phaseevolution = (TEs[echoes[1]] / ΔTE) .* romeo(angle.(hip); mag=weight, mask) # different from ASPIRE
    po .= getangle(image, echoes[1]) .- phaseevolution
    for icha in 1:size(po, 4)
        po[:,:,:,icha] .= gaussiansmooth3d_phase(po[:,:,:,icha], σ; mask)
    end
    combined = combinewithPO(image, po)
    if bipolar_correction
        G = bipolar_correction!(combined; TEs, σ, mask)
    end
    return combined
end

function combinewithPO(compl, po)
    combined = zeros(eltype(compl), size(compl)[1:4])
    for icha = 1:size(po, 4)
        @views combined .+= abs.(compl[:,:,:,:,icha]) .* compl[:,:,:,:,icha] ./ exp.(1im .* po[:,:,:,icha])
    end
    return combined ./ sqrt.(abs.(combined))
end

function bipolar_correction!(image; TEs, σ, mask)
    fG = artefact(image, TEs)
    fG .= gaussiansmooth3d_phase(fG, σ; mask)
    romeo!(fG; mag=getmag(image, 1)) # can be replaced by gradient-subtraction-unwrapping
    remove_artefact!(image, fG, TEs)
    return fG
end

getm(TEs) = TEs[1] / (TEs[2] - TEs[1])
getk(TEs) = (TEs[1] + TEs[3]) / TEs[2]

function artefact(I, TEs)
    k = getk(TEs)
    p2 = if abs(k - round(k)) < 0.01 # no unwrapping for integer k required
            getangle(I, 2)
        else
            romeo(getangle(I, 2); mag=getmag(I, 2))
        end
    return  getangle(I, 1) .+ getangle(I, 3) .- k .* p2
end

function remove_artefact!(image, fG, TEs)
    m = getm(TEs)
    k = getk(TEs)
    f = (2 - k) * m - k
    for ieco in 1:size(image, 4)
        t = ifelse(iseven(ieco), m + 1, m) / f
        subtract_angle!(image, ieco, t .* fG)
    end
end

function subtract_angle!(I, echo, sub)
    I[:,:,:,echo] ./= exp.(1im .* sub)
end

## PhaseMag functions
struct PhaseMag
    phase
    mag
end

function combinewithPO(image::PhaseMag, po)
    combined = zeros(Complex{eltype(image)}, size(image)[1:4])
    for icha = 1:size(po, 4)
        @views combined .+= image.mag[:,:,:,:,icha] .* image.mag[:,:,:,:,icha] .* exp.(1im .* (image.phase[:,:,:,:,icha] .- po[:,:,:,icha]))
    end
    return PhaseMag(angle.(combined), sqrt.(abs.(combined)))
end

function subtract_angle!(I::PhaseMag, echo, sub)
    I.phase[:,:,:,echo] .-= sub
    I.phase .= rem2pi.(I.phase, RoundNearest)
end

## Utility
Base.iterate(t::PhaseMag, i) = if i == 1 (t.phase, 2) else (t.mag, 3) end
Base.iterate(t::PhaseMag) = t.phase, t.mag
Base.eltype(t::PhaseMag) = promote_type(eltype(t.mag), eltype(t.phase))
Base.size(t::PhaseMag, args...) = size(t.phase, args...)
getHIP(data::PhaseMag; keyargs...) = getHIP(data.mag, data.phase; keyargs...)
getangle(c, echo) = angle.(ecoview(c, echo))
getangle(d::PhaseMag, echo) = ecoview(d.phase, echo)
getmag(c, echo) = abs.(ecoview(c, echo))
getmag(d::PhaseMag, echo) = ecoview(d.mag, echo)
ecoview(a, echo) = dimview(a, 4, echo)
dimview(a, dim, i) = view(a, ntuple(x -> if x == dim i else (:) end, ndims(a))...)


text:
pages = [
        "FastDEQ: Fast Deep Equilibrium Networks" => "index.md",
        "API" => [
            "Dynamical Systems" => "api/solvers.md",
            "Non Linear Solvers" => "api/nlsolve.md",
            "General Purpose Layers" => "api/layers.md",
            "DEQ Layers" => "api/deqs.md",
            "Miscellaneous" => "api/misc.md",
        ],
        "References" => "references.md",
    ]


text:
module _private

        mutable struct J3DWindow end
        mutable struct J3DShaderProgram end
        mutable struct VertexIndexArrayBufferObject end

end