text:
module RoadRunnerJulia
__precompile__(false)

export loada
export createRRInstance
export simulate
export getFloatingSpeciesIds
export steadyState

using Libdl
push!(Libdl.DL_LOAD_PATH, "./")
current_dir = @__DIR__
rr_api = joinpath(current_dir, "roadrunner_c_api.dll")
antimony_api = joinpath(current_dir, "libantimony.dll")

rrlib = Libdl.dlopen(rr_api)
antlib = Libdl.dlopen(antimony_api)
# Libdl.dlopen("C:/vs_rebuild/install/roadrunner/bin/roadrunner_c_api.dll")

# println("this is the value of rrlib outside of the function: ", rrlib)
#a = 1000
#k = Array{Float64}(undef, 100)
include("rrc_utilities_binding.jl")
include("rrc_types.jl")
include("antimony_binding.jl")

# function __init__()
#   global rrlib = Libdl.dlopen("C:/vs_rebuild/install/roadrunner/bin/roadrunner_c_api.dll")
#   global antlib = Libdl.dlopen("C:/Users/lukez/OneDrive/Desktop/Network Generator/Network-Generator/libantimony.dll")
# end

function loada(antString::String)
  rr = createRRInstance()
  try
    loadAntimonyString(antString)
    numModules = getNumModules()
    moduleName = getNthModuleName(numModules - 1)
    sbmlModel = getSBMLString(moduleName)
    loadSBML(rr, sbmlModel)
  finally
    freeAll()
    clearPreviousLoads()
  end
    return rr
end

###############################################################################
#            Library Initialization and Termination Methods                   #
###############################################################################
function createRRInstance()
  val = ccall(dlsym(rrlib, :createRRInstance), cdecl, Ptr{Nothing}, ())
  if val == C_NULL
    error("Failed to start up roadRunner")
  end
  return val
end

function createRRInstanceEx(tempFolder::String, compiler_cstr::String)
  val = ccall(dlsym(rrlib, :createRRInstanceEx), cdecl, Ptr{Nothing}, (Ptr{UInt8}, Ptr{UInt8}), tempFolder, compiler_cstr)
  return val
end

function freeRRInstance(rr::Ptr{Nothing})
  free_status = ccall(dlsym(rrlib, :freeRRInstance), cdecl, Bool, (Ptr{Nothing},), rr)
  if free_status == false
    error(getLastError())
  end
end

function getInstallFolder()
  str = ccall(dlsym(rrlib, :getInstallFolder), cdecl, Ptr{UInt8}, ())
end

function setInstallFolder(folder::String)
  status = ccall(dlsym(rrlib, :setInstallFolder), cdecl, Bool, (Ptr{UInt8},), folder)
  if status == false
    error(getLastError())
  end
end

function setComputeAndAssignConservationLaws(rr::Ptr{Nothing}, OnOrOff::Bool)
  status = ccall(dlsym(rrlib, :setComputeAndAssignConservationLaws), cdecl, Bool, (Ptr{Nothing} , Bool), rr, OnOrOff)
  if status == false
    error(getLastError())
  end
end

###############################################################################
#                            Read and Write Models                            #
###############################################################################
function loadSBML(rr::Ptr{Nothing}, sbml::String)
  status = ccall(dlsym(rrlib, :loadSBML), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}), rr, sbml)
  if status == false
    error(getLastError())
  end
end

function loadSBMLEx(rr::Ptr{Nothing}, sbml::String, forceRecompile::Bool)
  status = ccall(dlsym(rrlib, :loadSBMLEx), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Bool), rr, sbml, forceRecompile)
  if status == false
    error(getLastError())
  end
end

function loadSBMLFromFile(rr::Ptr{Nothing}, fileName::String)
  status = ccall(dlsym(rrlib, :loadSBMLFromFile), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}), rr, fileName)
  if status == false
    error(getLastError())
  end
end

function loadSBMLFromFileE(rr::Nothing, fileName::String, forceRecompile::Bool)
  status = ccall(dlsym(rrlib, :loadSBMLFromFileE), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Bool), rr, fileName, forceRecompile)
  if status == false
    error(getLastError())
  end
end

function clearModel(rr::Ptr{Nothing})
  status = ccall(dlsym(rrlib, :clearModel), cdecl, Int8, (Ptr{Nothing}, ), rr)
  if status == false
    error(getLastError())
  end
end

function isModelLoaded(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :isModelLoaded), cdecl, Bool, (Ptr{Nothing},), rr)
end

function loadSimulationSettings(rr::Ptr{Nothing}, fileName::String)
  status = call(dlsym(rrlib, :loadSimulationSettings), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}), rr, fileName)
  if status == false
    error(getLastError())
  end
end

function getCurrentSBML(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentSBML), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function getSBML(rr::Ptr{Nothing})
   return unsafe_string(ccall(dlsym(rrlib, :getSBML), Ptr{UInt8}, (Ptr{Nothing},), rr))
end

###############################################################################
#                          Utilities Functions                               #
###############################################################################

function getAPIVersion()
  return unsafe_string(ccall(dlsym(rrlib, :getAPIVersion), cdecl, Ptr{UInt8}, ()))
end

function getCPPAPIVersion(rr)
  return unsafe_string(ccall(dlsym(rrlib, :getCPPAPIVersion), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function getVersion()
  return ccall(dlsym(rrlib, :getVersion), cdecl, Int64, ())
end

function getVersionStr()
  return unsafe_string(ccall(dlsym(rrlib, :getVersionStr), cdecl, Ptr{UInt8}, ()))
end

function getVersionEx()
  return unsafe_string(ccall(dlsym(rrlib, :getVersionEx), cdecl, Ptr{UInt8}, ()))
end

function getExtendedAPIInfo()
  return unsafe_string(ccall(dlsym(rrlib, :getExtendedAPIInfo), cdecl, Ptr{UInt8}, ()))
end

function getBuildDate()
  return unsafe_string(ccall(dlsym(rrlib, :getBUildDate), cdecl, Ptr{UInt8}, ()))
end

function getBuildTime()
  return unsafe_string(ccall(dlsym(rrlib, :getBuildTime), cdecl, Ptr{UInt8}, ()))
end

function getBuildDateTime()
  return unsafe_string(ccall(dlsym(rrlib, :getBuildDateTime), cdecl, Ptr{UInt8}, ()))
end

function getCopyright()
  return unsafe_string(ccall(dlsym(rrlib, :getCopyright), cdecl, Ptr{UInt8}, ()))
end

function getInfo(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getInfo), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function getlibSBMLVersion(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getlibSBMLVersion), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function setTempFolder(rr::Ptr{Nothing}, folder::String)
  status = ccall(dlsym(rrlib, :setTempFolder), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}), rr, folder)
  if status == false
    error(getLastError())
  end
end

function getTempFolder(rr::Ptr{Nothing})
  return unsafe_string(ccal(dlsym(rrlib, :getTempFolder), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function getWorkingDirectory()
  return unsafe_string(ccall(dlsym(rrlib, :getWorkingDirectory), cdecl, Ptr{UInt8}, ()))
end

function getRRCAPILocation()
  return unsafe_string(ccall(dlsym(rrlib, :getRRCAPILocation), cdecl, Ptr{UInt8}, ()))
end

function setCompiler(rr::Ptr{Nothing}, fName::String)
  status = ccall(dlsym(rrlib, :setCompiler), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}), rr, fName)
  if status == false
    error(getLastError())
  end
end

function getCompiler(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getCompiler), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function setCompilerLocation(rr::Ptr{Nothing}, folder::String)
  status = ccall(dlsym(rrlib, :setCompilerLocation), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}), rr, folder)
  if status == false
    error(getLastError())
  end
end

function getCompilerLocation(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getCompilerLocation), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function setSupportCodeFolder(rr::Ptr{Nothing}, folder::String)
  status = ccall(dlsym(rrlib, :setSupportCodeFolder), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}), rr, folder)
  if status == false
    error(getLastError())
  end
end

function getSupportCodeFolder(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getSupportCodeFolder), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function setCodeGenerationMode(rr::Ptr{Nothing}, mode::Int64)
  status = ccall(dlsym(rrlib, :setCodeGenerationMode), cdecl, Bool, (Ptr{Nothing}, Int64), rr, mode)
  if status == false
    error(getLastError())
  end
end

###############################################################################
#                      Error Handling Functions                               #
###############################################################################

function hasError()
  return ccall(dlsym(rrlib, :hasError), cdecl, Bool, ())
end

function getLastError()
  return unsafe_string(ccall(dlsym(rrlib, :getLastError), cdecl, Ptr{UInt8}, ()))
end

###############################################################################
#                         Logging Functionality                               #
###############################################################################

function enableLoggingToConsole()
  status = ccall(dlsym(rrlib, :enableLoggingToConsole), cdecl, Int8, ())
  if status == false
    error(getLastError())
  end
end

function disableLoggingToConsole()
  status = ccall(dlsym(rrlib, :disableLoggingToConsole), cdecl, Bool, ())
  if status == false
    error(getLastError())
  end
end

function enableLoggingToFile()
  status = ccall(dlsym(rrlib, :enableLoggingToFile), cdecl, Bool, ())
  if status == false
    error(getLastError())
  end
end

function enableLoggingToFileWithPath(path::String)
  status = ccall(dlsym(rrlib, :enableLoggingToConsole), cdecl, Bool, (Ptr{UInt8},), path)
  if status == false
    error(getLastError())
  end
end

function disableLoggingToFile()
  status = ccall(dlsym(rrlib, :disableLoggingToFile), cdecl, Bool, ())
  if status == false
    error(getLastError())
  end
end

function setLogLevel(lvl::String)
  return ccall(dlsym(rrlib, :setLogLevel), cdecl, Int8, (Ptr{UInt8},), lvl)
end

function getLogLevel()
  return unsafe_string(ccall(dlsym(rrlib, :getLogLevel), cdecl, Ptr{UInt8}, ()))
end

function getLogFileName()
  return unsafe_string(ccall(dlsym(rrlib, :getLogFileName), cdecl, Ptr{UInt8}, ()))
end

## Todo, enum type
function logMsg()
end

###############################################################################
#                         Current State of System                             #
###############################################################################
function getValue(rr::Ptr{Nothing}, symbolId::String)
  #value = Array{Float64}(undef,1)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getValue), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Ptr{Float64}), rr, symbolId, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

function setValue(rr::Ptr{Nothing}, symbolId::String, value::Float64)
  status = ccall(dlsym(rrlib, :setValue), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Float64), rr, symbolId, value)
  if status == false
    error(getLastError())
  end
end

function evalModel(rr::Ptr{Nothing})
  status = ccall(dlsym(rrlib, :evalModel), cdecl, Bool, (Ptr{Nothing},), rr)
  if status == false
    error(getLastError())
  end
end

## To test
function getEigenvalueIds(rr::Ptr{Nothing})
  data = ccall(dlsym(rrlib, :getEigenvalueIds), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr)
  eigenValueIds = convertStringArrayToJuliaArray(data)
  return eigenValueIds
end

function getAvailableTimeCourseSymbols(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getAvailableTimeCourseSymbols), cdecl, Ptr{RRList}, (Ptr{Nothing},), rr)
end

function getAvailableSteadyStateSymbols(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getAvailableSteadyStateSymbols), cdecl, Ptr{RRList}, (Ptr{Nothing},), rr)
end

###############################################################################
#                         Time Course Simulation                              #
###############################################################################

function setConfigurationXML(rr::Ptr{Nothing}, caps::String)
  status = ccall(dlsym(rrlib, :setConfigurationXML), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}), rr, caps)
  if status == false
    error(getLastError())
  end
end

function getConfigurationXML(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getConfigurationXML), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function setTimeStart(rr::Ptr{Nothing}, timeStart::Number)
   status = ccall(dlsym(rrlib, :setTimeStart), cdecl, Bool, (Ptr{Nothing}, Float64), rr, timeStart)
   if status == false
     error(getLastError())
   end
end

function setTimeEnd(rr::Ptr{Nothing}, timeEnd::Number)
  status = ccall(dlsym(rrlib, :setTimeEnd), cdecl, Bool, (Ptr{Nothing}, Float64), rr, timeEnd)
  if status == false
    error(getLastError())
  end
end

function setNumPoints(rr::Ptr{Nothing}, nrPoints::Int64)
  status = ccall(dlsym(rrlib, :setNumPoints), cdecl, Bool, (Ptr{Nothing}, Int64), rr, nrPoints)
  if status == false
    error(getLastError())
  end
end

function setTimeCourseSelectionList(rr::Ptr{Nothing}, list::String)
  status = ccall(dlsym(rrlib, :setTimeCourseSelectionList), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}), rr, list)
  if status == false
    error(getLastError())
  end
end

## RRStringArray Helper
function getTimeCourseSelectionList(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getTimeCourseSelectionList), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr)
end

function simulate(rr::Ptr{Nothing})
  data = ccall(dlsym(rrlib, :simulate), cdecl, Ptr{RRCData}, (Ptr{Nothing},), rr)
  print(data)
  return simulate_helper(data)
end

## Handle RRCData
function getSimulationResult(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getSimulationResult), cdecl, Ptr{RRCData}, (Ptr{Nothing},), rr)
end

# calls simulateEx
function simulate(rr::Ptr{Nothing}, startTime::Number, endTime::Number, steps::Int)
  data = ccall(dlsym(rrlib, :simulateEx), cdecl, Ptr{RRCData}, (Ptr{Nothing}, Cdouble, Cdouble, Cint), rr, startTime, endTime, steps)
  return simulate_helper(data)
end

function simulate_helper(data::Ptr{RRCData})
  num_row = getRRDataNumRows(data)
  num_col = getRRDataNumCols(data)
  data_arr = Array{Float64}(undef, num_row, num_col)
  try
    for r = 1:num_row
        for c = 1:num_col
            data_arr[r, c] = getRRCDataElement(data, r - 1, c - 1)
        end
    end
  catch e
    throw(e)
  finally
    freeRRCData(data)
  end
  return data_arr
end

function oneStep(rr::Ptr{Nothing}, currentTime::Float64, stepSize::Float64)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :oneStep), cdecl, Bool, (Ptr{Nothing}, Float64, Float64, Ptr{Float64}), rr, currentTime, stepSize, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

function getTimeStart(rr::Ptr{Nothing})
  timeStart = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getTimeStart), cdecl, Bool, (Ptr{Nothing}, Ptr{Float64}), rr, timeStart)
  if status == false
    error(getLastError())
  end
  return timeStart[1]
end

function getTimeEnd(rr::Ptr{Nothing})
  #timeEnd = Array(Float64, 1)
  timeEnd = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getTimeEnd), cdecl, Bool, (Ptr{Nothing}, Ptr{Float64}), rr, timeEnd)
  if status == false
    error(getLastError())
  end
  return timeEnd[1]
end

function getNumPoints(rr)
  numPoints = Array{Int64}(undef,1)
  status = ccall(dlsym(rrlib, :getNumPoints), cdecl, Bool, (Ptr{Nothing}, Ptr{Int64}), rr, numPoints)
  if status == false
    error(getLastError())
  end
  return numPoints[1]
end

###############################################################################
#                            Steady State Routines                            #
###############################################################################
function steadyState(rr::Ptr{Nothing})
  value = Array{Float64}(undef, 1)
  status = ccall(dlsym(rrlib, :steadyState), cdecl, Bool, (Ptr{Nothing}, Ptr{Float64}), rr, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

## RRVectorHelper
function computeSteadyStateValues(rr::Ptr{Nothing})
  rrVector = ccall(dlsym(rrlib, :computeSteadyStateValues), cdecl, Ptr{RRVector}, (Ptr{Nothing},), rr)
  if rrVector == C_NULL
    error(getLastError())
  else
    ssValues = convertRRVectorToJuliaArray(rrVector)
    return ssValues
  end
end

function setSteadyStateSelectionList(rr::Ptr{Nothing}, list::String)
  status = ccall(dlsym(rrlib, :setSteadyStateSelectionList), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Ptr{UInt8}), rr, list)
  if status == false
    error(getLastError())
  end
end

## RRStringArray Helper
function getSteadyStateSelectionList(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getSteadyStateSelectionList), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr)
end

###############################################################################
#                               Reaction Group                                #
###############################################################################

function getNumberOfReactions(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getNumberOfReactions), cdecl, Int64, (Ptr{Nothing},), rr)
end

function getReactionRate(rr::Ptr{Nothing}, idx::Int64)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getReactionRate), cdecl, Bool, (Ptr{Nothing}, Int64, Ptr{Float64}), rr, rateNr, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

### RRVector Helper
function getReactionRates(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getReactionRates), cdecl, Ptr{RRVector}, (Ptr{Nothing},), rr)
end

### RRVector Helper
function getReactionRatesEx(rr::Ptr{Nothing}, vec::Ptr{RRVector})
  return_vec = call(dlsym(rrlib, :getReactionRatesEx), cdecl, Ptr{RRVector}, (Ptr{Nothing}, Ptr{RRVector}), rr, vec)
  return return_vec
end

function getReactionIds(rr::Ptr{Nothing})
  data = ccall(dlsym(rrlib, :getReactionIds), cdecl, Ptr{Nothing}, (Ptr{Nothing},), rr)
  num_rxns = getNumberOfReactions(rr)
  rxnIds = String[]
  try
    for i = 1:num_rxns
      push!(rxnIds, getStringElement(data, i - 1))
    end
  catch e
    throw(e)
  finally
    freeStringArray(data)
  end
  return rxnIds
end

###############################################################################
#                            Rates of Change Group                            #
###############################################################################

### RRVector Helper
function getRatesOfChange(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getRatesOfChange), cdecl, Ptr{RRVector}, (Ptr{Nothing},), rr)
end

### RRVector Helper
function getRatesOfChangeIds(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getRatesOfChangeIds), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr)
end

function getRateOfChange(rr::Ptr{Nothing}, index::Int64)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib :getRateOfChange), cdecl, Bool, (Ptr{Nothing}, Int64, Ptr{Float64}), rr, inde, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

## RRVector Helper
function getRatesOfChangeEx(rr::Ptr{Nothing}, vec::Ptr{RRVector})
  return ccall(dlsym(rrlib, :getRatesOfChangeEx), cdecl, Ptr{Nothing}, (Ptr{Nothing}, Ptr{RRVector}), rr, vec)
end

###############################################################################
#                           Boundary Species Group                            #
###############################################################################

## RRVectorHelper
function getBoundarySpeciesConcentrations(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getBoundarySpeciesConcentrations), cdecl, Ptr{RRVector}, (Ptr{Nothing},), rr)
end

function setBoundarySpeciesByIndex(rr::Ptr{Nothing}, index::Int64, value::Float64)
  status = ccall(dlsym(rrlib, :setBoundarySpeciesByIndex), cdecl, Bool, (Ptr{Nothing}, Int64, Float64), rr, index, value)
  if status == false
    error(getLastError())
  end
end

function getBoundarySpeciesByIndex(rr::Ptr{Nothing}, index::Int64)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getBoundarySpeciesByIndex), cdecl, Bool, (Ptr{Nothing}, Int64, Ptr{Float64}), rr, index, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

## RRVectorHelper
function setBoundarySpeciesConcentrations(rr::Ptr{Nothing}, vec::Ptr{RRVector})
  status = ccall(dlsym(rrlib, :setFloatingSpeciesInitialConcentrations), cdecl, Bool, (Ptr{Nothing}, Ptr{RRVector}), rr, vec)
  if status == false
    error(getLastError())
  end
end

function getNumberOfBoundarySpecies(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getNumberOfBoundarySpecies), cdecl, Int64, (Ptr{Nothing},), rr)
end

function getBoundarySpeciesIds(rr::Ptr{Nothing})
  data = ccall(dlsym(rrlib, :getBoundarySpeciesIds), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr)
  b_species = String[]
  try
    num_b_species = getNumberOfBoundarySpecies(rr)
    for i = 1:num_b_species
      push!(b_species, getStringElement(data, i - 1))
    end
  catch e
    throw(e)
  finally
    freeStringArray(data)
  end
  return b_species
end

###############################################################################
#                           Floating Species Group                            #
###############################################################################

## RRVectorHelper
function getFloatingSpeciesConcentrations(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getFloatingSpeciesConcentrations), cdecl, Ptr{RRVector}, (Ptr{Nothing},), rr)
end

function setFloatingSpeciesInitialConcentrationByIndex(rr::Ptr{Nothing}, index::Int64, value::Float64)
  status = call(dlsym(rrlib, :setFloatingSpeciesInitialConcentrationByIndex), cdecl, Bool, (Ptr{Nothing}, Int64, Float64), rr, index, value)
  if status == false
    error(getLastError())
  end
end

function getFloatingSpeciesInitialConcentrationByIndex(rr::Ptr{Nothing}, index::Int64)
  value = Array{Floating64}(undef,1)
  status = ccall(dlsym(rrlib, :getFloatingSpeciesInitialConcentrationByIndex), cdecl, Bool, (Ptr{Nothing}, Int64, Ptr{Float64}), rr, index, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

function setFloatingSpeciesByIndex(rr::Ptr{Nothing}, index::Int64, value::Float64)
  status = ccall(dlsym(rrlib, :setFloatingSpeciesByIndex), cdecl, Bool, (Ptr{Nothing}, Int64, Float64), rr, index, value)
  if status == false
    error(getLastError())
  end
end

function getFloatingSpeciesByIndex(rr::Ptr{Nothing}, index::Int64)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getFloatingSpeciesByIndex ), cdecl, Bool, (Ptr{Nothing}, Int64, Ptr{Float64}), rr, index, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

function setFloatingSpeciesConcentrations(rr::Ptr{Nothing}, vec::Ptr{RRVector})
  status = ccall(dlsym(rrlib, :setFloatingSpeciesInitialConcentrations), cdecl, Bool, (Ptr{Nothing}, Ptr{RRVector}), rr, vec)
  if status == false
    error(getLastError())
  end
end

function getNumberOfFloatingSpecies(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getNumberOfFloatingSpecies), cdecl, Int64, (Ptr{Nothing},), rr)
end

function getNumberOfDependentSpecies(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getNumberOfDependentSpecies), cdecl, Int64, (Ptr{Nothing},), rr)
end

function getNumberOfIndependentSpecies(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getNumberOfIndependentSpecies), cdecl, Int64, (Ptr{Nothing},), rr)
end

function getFloatingSpeciesIds(rr::Ptr{Nothing})
  data = ccall(dlsym(rrlib, :getFloatingSpeciesIds), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr)
  species = String[]
  try
    num_species = getNumberOfFloatingSpecies(rr)
    for i = 1:num_species
      push!(species, getStringElement(data, i - 1))
    end
  catch e
    throw(e)
  finally
    freeStringArray(data)
  end
  return species
end

###############################################################################
#                           Intial Conditions Group                           #
###############################################################################

function setFloatingSpeciesInitialConcentrations(rr::Ptr{Nothing}, vec::Ptr{RRVector})
  status = ccall(dlsym(rrlib, :setFloatingSpeciesInitialConcentrations), cdecl, Bool, (Ptr{Nothing}, Ptr{RRVector}), rr, vec)
  if status == false
    error(getLastError())
  end
end

## RRVectorHelper
function getFloatingSpeciesInitialConcentrations(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getFloatingSpeciesInitialConcentrations), cdecl, Ptr{RRVector}, (Ptr{Nothing},), rr)
end

## RRStringArrayHelper
function getFloatingSpeciesInitialConditionIds(rr::Ptr{Nothing})
  data = ccall(dlsym(rrlib, :getFloatingSpeciesInitialConditionIds), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr)
  return data
end

###############################################################################
#                              Parameters Group                               #
###############################################################################

## RRVectorHelper
function getGlobalParameterValues(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getGlobalParameterValues), cdecl, Ptr{RRVector}, (Ptr{Nothing},), rr)
end

function setGlobalParameterByIndex(rr::Ptr{Nothing}, index::Int64, value::Float64)
  status = ccall(dlsym(rrlib, :setGlobalParameterByIndex), cdecl, Bool, (Ptr{Nothing}, Int64, Float64), rr, index, value)
  if status == false
    error(getLastError())
  end
end

function getGlobalParameterByIndex(rr::Ptr{Nothing}, index::Int64)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getGlobalParameterByIndex ), cdecl, Bool, (Ptr{Nothing}, Int64, Ptr{Float64}), rr, index, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

function getNumberOfGlobalParameters(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getNumberOfGlobalParameters), cdecl, Int64, (Ptr{Nothing},), rr)
end

function getGlobalParameterIds(rr::Ptr{Nothing})
  data = ccall(dlsym(rrlib, :getGlobalParameterIds), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr)
  global_params = String[]
  try
    num_elem = getNumberOfGlobalParameters(rr)
    for i = 1:num_elem
      push!(global_params, getStringElement(data, i - 1))
    end
  catch e
    throw(e)
  finally
    freeStringArray(data)
  end
  return global_params
end

###############################################################################
#                              Compartment Group                              #
###############################################################################

function getCompartmentByIndex(rr::Ptr{Nothing}, index::Int64)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib :getCompartmentByIndex), cdecl, Bool, (Ptr{Nothing}, Int64, Ptr{Float64}), rr, index, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

function setCompartmentByIndex(rr::Ptr{Nothing}, index::Int64, value::Float64)
  status = ccall(dlsym(rrlib, :setCompartmentByIndex), cdecl, Bool, (Ptr{Nothing}, Int64, Float64), rr, index, value)
  if status == false
    error(getLastError())
  end
end

function getNumberOfCompartments(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getNumberOfCompartments), cdecl, Int64, (Ptr{Nothing},), rr)
end

function getCompartmentIds(rr::Ptr{Nothing})
  data = ccall(dlsym(rrlib, :getCompartmentIds), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr)
  compartmentIds = String[]
  try
    num_elem = getNumberOfCompartments(rr)
    for i = 1:num_elem
      push!(compartmentIds, getStringElement(data, i - 1))
    end
  catch e
    throw(e)
  finally
    freeStringArray(data)
  end
  return compartmentIds
end

###############################################################################
#                        Metabolic Control Analysis                           #
###############################################################################

## RRListHelper
function getElasticityCoefficientIds(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getElasticityCoefficientIds), cdecl, Ptr{RRList}, (Ptr{Nothing},), rr)
end

## RRListHelper
function getUnscaledFluxControlCoefficientIds(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getUnscaledFluxControlCoefficientIds), cdecl, Ptr{RRList}, (Ptr{Nothing},), rr)
end

## RRListHelper
function getFluxControlCoefficientIds(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getFluxControlCoefficientIds), cdecl, Ptr{RRList}, (Ptr{Nothing},), rr)
end

## RRListHelper
function getUnscaledConcentrationControlCoefficientIds(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getUnscaledConcentrationControlCoefficientIds), cdecl, Ptr{RRList}, (Ptr{Nothing},), rr)
end

## RRListHelper
function getConcentrationControlCoefficientIds(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getConcentrationControlCoefficientIds), cdecl, Ptr{RRList}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getUnscaledElasticityMatrix(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getUnscaledElasticityMatrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getScaledElasticityMatrix(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getScaledElasticityMatrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

function getScaledFloatingSpeciesElasticity(rr::Ptr{Nothing}, reactionId::String, speciesId::String)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getScaledFloatingSpeciesElasticity), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Ptr{UInt8}, Ptr{Float64}), rr, reactionId, speciesId, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

## RRDoubleMatrixHelper
function getUnscaledConcentrationControlCoefficientMatrix(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getUnscaledConcentrationControlCoefficientMatrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getScaledConcentrationControlCoefficientMatrix(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getScaledConcentrationControlCoefficientMatrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getUnscaledFluxControlCoefficientMatrix(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getUnscaledFluxControlCoefficientMatrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getScaledFluxControlCoefficientMatrix(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getScaledFluxControlCoefficientMatrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

function getuCC(rr::Ptr{Nothing}, variable::String, parameter::String)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getuCC), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Ptr{UInt8}, Ptr{Float64}), rr, variable, parameter, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

function getCC(rr::Ptr{Nothing}, variable::String, parameter::String)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getCC), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Ptr{UInt8}, Ptr{Float64}), rr, variable, parameter, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

function getEE(rr::Ptr{Nothing}, name::String, species::String)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getEE), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Ptr{UInt8}, Ptr{Float64}), rr, name, species, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

function getuEE(rr::Ptr{Nothing}, name::String, species::String)
  value = Array{Float64}(undef,1)
  status = ccall(dlsym(rrlib, :getuEE), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Ptr{UInt8}, Ptr{Float64}), rr, name, species, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

###############################################################################
#                           Stochastic Simulation                             #
###############################################################################

function getSeed(rr::Ptr{Nothing})
  value = Array{Float32}(undef,1)
  status = ccall(dlsym(rrlib, :getSeed), cdecl, Bool, (Ptr{Nothing}, Ptr{Float32}), rr, value)
  if status == false
    error(getLastError())
  end
  return value[1]
end

function setSeed(rr::Ptr{Nothing}, result::Float32)
  status = ccall(dlsym(rrlib, :setSeed), cdecl, Bool, (Ptr{Nothing}, Float32), rr, result)
  if status == false
    error(getLastError())
  end
end

## RRCDataHelper
function gillespie(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :gillespie), cdecl, Ptr{RRCData}, (Ptr{Nothing},), rr)
end

## RRCDataHelper
function gillespieEx(rr::Ptr{Nothing}, timeStart::Float64, timeEnd::Float64)
  return ccall(dlsym(rrlib, :gillespieEx), cdecl, Ptr{RRCData}, (Ptr{Nothing}, Float64, Float64), rr, timeStart, timeEnd)
end

## RRCDataHelper
function gillespieOnGrid(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :gillespieOnGrid), cdecl, Ptr{RRCData}, (Ptr{Nothing},), rr)
end

## RRCDataHelper
function gillespieOnGridEx(rr::Ptr{Nothing}, timeStart::Float64, timeEnd::Float64, numberOfPoints::Int64)
  return ccall(dlsym(rrlib, :gillespieOnGridEx), cdecl, Ptr{RRCData}, (Ptr{Nothing}, Float64, Float64, Int64), rr, timeStart, timeEnd, numberOfPoints)
end

## RRCDataHelper
function gillespieMeanOnGrid(rr::Ptr{Nothing}, numberOfSimulations::Int64)
  return ccall(dlsym(rrlib, :gillespieMeanOnGrid), cdecl, Ptr{RRCData}, (Ptr{Nothing}, Int64), rr, numberOfSimulations)
end

## RRCDataHelper
function gillespieMeanOnGridEx(rr::Ptr{Nothing}, timeStart::Float64, timeEnd::Float64, numberOfPoints::Int64, numberOfSimulations::Int64)
  return ccall(dlsym(rrlib, :gillespieMeanOnGridEx), cdecl, Ptr{RRCData}, (Ptr{Nothing}, Float64, Float64, Int64, Int64), rr, timeStart, timeEnd, numberOfPoints, numberOfSimulations)
end

## RRCDataHelper
function gillespieMeanSDOnGrid(rr::Ptr{Nothing}, numberOfSimulations::Int64)
  return ccall(dlsym(rrlib, :gillespieMeanSDOnGrid), cdecl, Ptr{RRCData}, (Ptr{Nothing}, Int64), rr, numberOfSimulations)
end

## RRCDataHelper
function gillespieMeanSDOnGridEx(rr::Ptr{Nothing}, timeStart::Float64, timeEnd::Float64, numberOfPoints::Int64, numberOfSimulations::Int64)
  return ccall(dlsym(rrlib, :gillespieMeanSDOnGridEx), cdecl, Ptr{RRCData}, (Ptr{Nothing}, Float64, Float64, Int64, Int64), rr, timeStart, timeEnd, numberOfPoints, numberOfSimulations)
end

###############################################################################
#                           Stoichiometry Analysis                            #
###############################################################################

## RRDoubleMatrixHelper
function getFullJacobian(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getFullJacobian), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getReducedJacobian(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getReducedJacobian), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getEigenvalues(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getEigenvalues), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getStoichiometryMatrix(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getStoichiometryMatrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getLinkMatrix(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getLinkMatrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getNrMatrix(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getNrMatrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getConservationMatrix(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getConservationMatrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRDoubleMatrixHelper
function getL0Matrix(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getL0Matrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{Nothing},), rr)
end

## RRComplexMatrixHelper
function getEigenVectors(matrix::Ptr{RRComplexMatrix})
  return ccall(dlsym(rrlib, :getEigenVectors), cdecl, Ptr{RRComplexMatrix}, (Ptr{RRComplexMatrix},), rr)
end

## RRComplexMatrixHelper
function getZEigenVectors(matrix::Ptr{RRComplexMatrix})
  return ccall(dlsym(rrlib, :getZEigenVectors), cdecl, Ptr{RRComplexMatrix}, (Ptr{RRComplexMatrix},), rr)
end

## RRVector
function getConservedSums(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getConservedSums), cdecl, Ptr{RRVector}, (Ptr{Nothing},), rr)
end

###############################################################################
#                      Network Object Model Functions                         #
###############################################################################

function getNumberOfRules(rr::Ptr{Nothing})
  result = ccall(dlsym(rrlib, :getConservedSums), cdecl, Cint, (Ptr{Nothing},), rr)
  if result == -1
    error(getLastError())
  end
end

## could return null, error checking
function getModelName(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getModelName), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

###############################################################################
#                           Linear Algebra Functions                          #
###############################################################################
## RRDoubleMatrixHelper
function getEigenvaluesMatrix(mat::Ptr{RRDoubleMatrix})
  return ccall(dlsym(rrlib, :getEigenvaluesMatrix), cdecl, Ptr{RRDoubleMatrix}, (Ptr{RRDoubleMatrix},), rr)
end

## RRComplexVectorHelper
function getEigenvaluesVector(mat::Ptr{RRDoubleMatrix})
  return ccall(dlsym(rrlib, :getEigenvaluesVector), cdecl, Ptr{RRComplexVector}, (Ptr{RRDoubleMatrix},), rr)
end

###############################################################################
#                               Reset Methods                                 #
###############################################################################
function resetRR(rr::Ptr{Nothing})
  status = ccall(dlsym(rrlib, :reset), cdecl, Bool, (Ptr{Nothing},), rr)
  if status == false
    error(getLastError())
  end
end

function resetAllRR(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :resetAll), cdecl, Bool, (Ptr{Nothing},), rr)
  if status == false
    error(getLastError())
  end
end

function resetToOriginRR(rr::Ptr{Nothing})
  status = ccall(dlsym(rrlib, :resetToOrigin), cdecl, Bool, (Ptr{Nothing},), rr)
  if status == false
    error(getLastError())
  end
end

###############################################################################
#                          Solver Options and APIs                            #
###############################################################################

function getNumRegisteredIntegrators()
  return ccall(dlsym(rrlib, :getNumRegisteredIntegrators), cdecl, Cint, ())
end

function getRegisteredIntegratorName(n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getRegisteredIntegratorName), cdecl, Ptr{UInt8}, (Cint,), n))
end

function getRegisteredIntegratorHint(n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getRegisteredIntegratorHint), cdecl, Ptr{UInt8}, (Cint,), n))
end

function getRegisteredIntegratorDescription(n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getRegisteredIntegratorDescription), cdecl, Ptr{UInt8}, (Cint,), n))
end

function getNumInstantiatedIntegrators(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getNumInstantiatedIntegrators), cdecl, Cint, (Ptr{Nothing},), rr)
end

function setCurrentIntegrator(rr::Ptr{Nothing}, nameOfIntegrator::String)
  result = ccall(dlsym(rrlib, :setCurrentIntegrator), cdecl, Cint, (Ptr{Nothing}, String), rr, nameOfIntegrator)
  if result == 0
    error(getLastError())
  end
end

function getCurrentIntegratorName(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentIntegratorName), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function getCurrentIntegratorDescription(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentIntegratorDescription), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function getCurrentIntegratorHint(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentIntegratorHint), cdecl, Ptr{UInt8}, (Ptr{Nothing},), rr))
end

function getNumberOfCurrentIntegratorParameters(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getNumberOfCurrentIntegratorParameters), cdecl, Cint, (Ptr{Nothing}, ), rr)
end

function getCurrentIntegratorNthParameterName(rr::Ptr{Nothing}, n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentIntegratorNthParameterName), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Cint), rr, n))
end

function getCurrentIntegratorNthParameterDescription(rr::Ptr{Nothing}, n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentIntegratorNthParameterDescription), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Cint), rr, n))
end

function getCurrentIntegratorNthParameterDisplayName(rr::Ptr{Nothing}, n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentIntegratorNthParameterDisplayName), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Cint), rr, n))
end

function getCurrentIntegratorNthParameterHint(rr::Ptr{Nothing}, n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentIntegratorNthParameterHint), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Cint), rr, n))
end

function getCurrentIntegratorNthParameterType(rr::Ptr{Nothing}, n::Int64)
  return ccall(dlsym(rrlib, :getCurrentIntegratorNthParameterType), cdecl, Cint, (Ptr{Nothing}, Cint), rr, n)
end

function resetCurrentIntegratorParameters(rr::Ptr{Nothing})
  result = ccall(dlsym(rrlib, :resetCurrentIntegratorParameters), cdecl, Cint, (Ptr{Nothing},), rr)
  if result == 0
    error(getLastError())
  end
end

## RRStringArrayHelper
function getListOfCurrentIntegratorParameterNames(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getListOfCurrentIntegratorParameterNames), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr)
end

function getCurrentIntegratorParameterDescription(rr::Ptr{Nothing}, parameterName::String)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentIntegratorParameterDescription), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName))
end

function getCurrentIntegratorParameterHint(rr::Ptr{Nothing}, parameterName::String)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentIntegratorParameterHint), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName))
end

function getCurrentIntegratorParameterType(rr::Ptr{Nothing}, parameterName::String)
  return ccall(dlsym(rrlib, :getCurrentIntegratorParameterType), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName)
end

function getCurrentIntegratorParameterInt(rr::Ptr{Nothing}, parameterName::String)
  return ccall(dlsym(rrlib, :getCurrentIntegratorParameterInt), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName)
end

function setCurrentIntegratorParameterInt(rr::Ptr{Nothing}, parameterName::String, value::Int64)
  return ccall(dlsym(rrlib, :setCurrentIntegratorParameterInt), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}, Cint), rr, parameterName, value)
end

function getCurrentIntegratorParameterUInt(rr::Ptr{Nothing}, parameterName::String)
  return ccall(dlsym(rrlib, :getCurrentIntegratorParameterUInt), cdecl, Cuint, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName)
end

function setCurrentIntegratorParameterUInt(rr::Ptr{Nothing}, parameterName::String, value::Int64)
  status = ccall(dlsym(rrlib, :setCurrentIntegratorParameterUInt), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}, Cint), rr, parameterName, value)
  if status == 0
    error(getLastError())
  end
end

function getCurrentIntegratorParameterDouble(rr::Ptr{Nothing}, parameterName::String)
  return ccall(dlsym(rrlib, :getCurrentIntegratorParameterUInt), cdecl, Cdouble, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName)
end

function setCurrentIntegratorParameterDouble(rr::Ptr{Nothing}, parameterName::String, value::Float64)
  status = ccall(dlsym(rrlib, :setCurrentIntegratorParameterUInt), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}, Cdouble), rr, parameterName, value)
  if status == 0
    error(getLastError())
  end
end

function getCurrentIntegratorParameterString(rr::Ptr{Nothing}, parameterName::String)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentIntegratorParameterString), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName))
end

function setCurrentIntegratorParameterString(rr::Ptr{Nothing}, parameterName::String, value::String)
  status = ccall(dlsym(rrlib, :getCurrentIntegratorParameterString), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}, Ptr{UInt8}), rr, parameterName, value)
  if status == 0
    error(getLastError())
  end
end

function getCurrentIntegratorParameterBoolean(rr::Ptr{Nothing}, parameterName::String)
  return ccall(dlsym(rrlib, :getCurrentIntegratorParameterUInt), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName)
end

function setCurrentIntegratorParameterBoolean(rr::Ptr{Nothing}, parameterName::String, value::Int64)
  status = ccall(dlsym(rrlib, :setCurrentIntegratorParameterBoolean), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}, Cint), rr, parameterName, value)
  if status == 0
    error(getLastError())
  end
end

function getNumRegisteredSteadyStateSolvers()
  return ccall(dlsym(rrlib, :getNumRegisteredIntegrators), cdecl, Cint, ())
end

function getRegisteredSteadyStateSolverName(n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getRegisteredSteadyStateSolverName), cdecl, Ptr{UInt8}, (Cint, ), n))
end

function getRegisteredSteadyStateSolverHint(n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getRegisteredSteadyStateSolverHint), cdecl, Ptr{UInt8}, (Cint, ), n))
end

function getRegisteredSteadyStateSolverDescription(n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getRegisteredSteadyStateSolverDescription), cdecl, Ptr{UInt8}, (Cint, ), n))
end

function setCurrentSteadyStateSolver(rr::Ptr{Nothing}, nameOfSteadyStateSolver::String)
  status = ccall(dlsym(rrlib, :getNumRegisteredIntegrators), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}), rr, nameOfSteadyStateSolver)
  if status == 0
    error(getLastError())
  end
end

function getCurrentSteadyStateSolverName(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentSteadyStateSolverName), cdecl, Ptr{UInt8}, (Ptr{Nothing}, ), rr))
end

function getCurrentSteadyStateSolverDescription(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentSteadyStateSolverDescription), cdecl, Ptr{UInt8}, (Ptr{Nothing}, ), rr))
end

function getCurrentSteadyStateSolverHint(rr::Ptr{Nothing})
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentSteadyStateSolverHint), cdecl, Ptr{UInt8}, (Ptr{Nothing}, ), rr))
end

function getNumberOfCurrentSteadyStateSolverParameters(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getCurrentSteadyStateSolverHint), cdecl, Cint, (Ptr{Nothing}, ), rr)
end

function getCurrentSteadyStateSolverNthParameterName(rr::Ptr{Nothing}, n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentSteadyStateSolverNthParameterName), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Cint), rr, n))
end

function getCurrentSteadyStateSolverNthParameterDisplayName(rr::Ptr{Nothing}, n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentSteadyStateSolverNthParameterDisplayName), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Cint), rr, n))
end

function getCurrentSteadyStateSolverNthParameterDescription(rr::Ptr{Nothing}, n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentSteadyStateSolverNthParameterDescription), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Cint), rr, n))
end

function getCurrentSteadyStateSolverNthParameterHint(rr::Ptr{Nothing}, n::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentSteadyStateSolverNthParameterHint), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Cint), rr, n))
end

function getCurrentSteadyStateSolverNthParameterType(rr::Ptr{Nothing}, n::Int64)
  return ccall(dlsym(rrlib, :getCurrentSteadyStateSolverNthParameterType), cdecl, Cint, (Ptr{Nothing}, Cint), rr, n)
end

function resetCurrentSteadyStateSolverParameters(rr::Ptr{Nothing})
  status = ccall(dlsym(rrlib, :resetCurrentSteadyStateSolverParameters), cdecl, Cint, (Ptr{Nothing},), rr)
  if status == 0
    error(getLastError())
  end
end

function solverTypeToString(code::Int64)
  return unsafe_string(ccall(dlsym(rrlib, :solverTypeToString), cdecl, Ptr{UInt8}, (Cint, ), code))
end

function getCurrentSteadyStateSolverNthParameterType(rr::Ptr{Nothing}, n::Int64)
  return ccall(dlsym(rrlib, :getCurrentSteadyStateSolverNthParameterType), cdecl, Cint, (Ptr{Nothing}, Cint), rr, n)
end

## RRString helper function
function getListOfCurrentSteadyStateSolverParameterNames(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :getListOfCurrentSteadyStateSolverParameterNames), cdecl, Ptr{RRStringArray}, (Ptr{Nothing}, ), rr)
end

function getCurrentSteadyStateSolverParameterDescription(rr::Ptr{Nothing}, parameterName::String)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentSteadyStateSolverParameterDescription), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName))
end

function getCurrentSteadyStateSolverParameterHint(rr::Ptr{Nothing}, parameterName::String)
  return unsafe_string(ccall(dlsym(rrlib, :getCurrentSteadyStateSolverParameterHint), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName))
end

function getCurrentSteadyStateSolverParameterType(rr::Ptr{Nothing}, parameterName::String)
  return ccall(dlsym(rrlib, :getCurrentSteadyStateSolverParameterType), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName)
end

function getCurrentSteadyStateSolverParameterInt(rr::Ptr{Nothing}, parameterName::String)
  return ccall(dlsym(rrlib, :getCurrentSteadyStateSolverParameterInt), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName)
end

function setCurrentSteadyStateSolverParameterInt(rr::Ptr{Nothing}, parameterName::String, value::Int64)
  status = ccall(dlsym(rrlib, :setCurrentSteadyStateSolverParameterInt), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}, Cint), rr, parameterName, value)
  if status == 0
    error(getLastError())
  end
end

function getCurrentSteadyStateSolverParameterUInt(rr::Ptr{Nothing}, parameterName::String)
  return ccall(dlsym(rrlib, :getCurrentSteadyStateSolverParameterUInt), cdecl, Cuint, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName)
end

function setCurrentSteadyStateSolverParameterUInt(rr::Ptr{Nothing}, parameterName::String, value::Int64)
  status = ccall(dlsym(rrlib, :setCurrentSteadyStateSolverParameterUInt), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}, Cint), rr, parameterName, value)
  if status == 0
    error(getLastError())
  end
end

function getCurrentSteadyStateSolverParameterDouble(rr::Ptr{Nothing}, parameterName::String)
  return ccall(dlsym(rrlib, :getCurrentSteadyStateSolverParameterUInt), cdecl, Cdouble, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName)
end

function setCurrentSteadyStateSolverParameterDouble(rr::Ptr{Nothing}, parameterName::String, value::Float64)
  status = ccall(dlsym(rrlib, :setCurrentSteadyStateSolverParameterDouble), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}, Cdouble), rr, parameterName, value)
  if status == 0
    error(getLastError())
  end
end

function getCurrentSteadyStateSolverParameterString(rr::Ptr{Nothing}, parameterName::String)
  return ccall(dlsym(rrlib, :getCurrentSteadyStateSolverParameterString), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName)
end

function setCurrentSteadyStateSolverParameterString(rr::Ptr{Nothing}, parameterName::String, value::String)
  status = ccall(dlsym(rrlib, :setCurrentSteadyStateSolverParameterString), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}, Ptr{UInt8}), rr, parameterName, value)
  if status == 0
    error(getLastError())
  end
end

function getCurrentSteadyStateSolverParameterBoolean(rr::Ptr{Nothing}, parameterName::String)
  return ccall(dlsym(rrlib, :getCurrentSteadyStateSolverParameterBoolean), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}), rr, parameterName)
end

function setCurrentSteadyStateSolverParameterBoolean(rr::Ptr{Nothing}, parameterName::String, value::Int64)
  status = ccall(dlsym(rrlib, :setCurrentSteadyStateSolverParameterBoolean), cdecl, Cint, (Ptr{Nothing}, Ptr{UInt8}, Cint), rr, parameterName, value)
  if status == 0
    error(getLastError())
  end
end

###############################################################################
#                        Configuration Keys and Values                        #
###############################################################################

function setConfigBool(key::String, value::Bool)
    status = ccall(dlsym(rrlib, :setConfigBool), cdecl, Bool, (Ptr{UInt8}, Cint), key, value)
    println(status)
    if status == false
      error(getLastError())
    # elseif status != true
    #   println("this is the status: ", status)
    #   println("boolean comparison: ", status != true)
    #   error("neither true nor false")
    end
    return status
end

function getConfigBool(key::String)
  return ccall(dlsym(rrlib, :getConfigBool), cdecl, Bool, (Ptr{UInt8},), key)
end

function setConfigInt(key::String, value::Int64)
    status = ccall(dlsym(rrlib, :setConfigInt), cdecl, Bool, (Ptr{UInt8}, Cint), key, value)
    println(status)
    if status == false
      error(getLastError())
    end
end

function getConfigInt(key::String)
  return ccall(dlsym(rrlib, :getConfigInt), cdecl, Int64, (Ptr{UInt8},), key)
end

function setConfigDouble(key::String, value::Float64)
  status = ccall(dlsym(rrlib, :setConfigDouble), cdecl, Bool, (Ptr{UInt8}, Cdouble), key, value)
  if status == false
    error(getLastError())
  end
end

function getConfigDouble(key::String)
  return ccall(dlsym(rrlib, :getConfigDouble), cdecl, Float64, (Ptr{UInt8},), key)
end

function getListOfConfigKeys()
  config_keys = String[]
  str_arr = ccall(dlsym(rrlib, :getListOfConfigKeys), cdecl, Ptr{RRStringArray}, ())
  num_element = getNumberOfStringElements(str_arr)
  for i = 1:num_element
    key = getStringElement(str_arr, i - 1)
    push!(config_keys, key)
  end
  freeStringArray(str_arr)
  return config_keys
end

### End

function resultsToJulia(resultHandle)
  rows = getRRDataNumRows(resultHandle)
  cols = getRRDataNumCols(resultHandle)
  results = Array{Float64}(undef, rows, cols)
  for i = 0:rows
    for j = 0:cols
      results[i + 1, j + 1] = getRRCDataElement(resultHandle, i, j)
    end
  end
  return results
end

function resultsColumn(resultHandle, column::Int64)
  rows = getRRDataNumRows(resultHandle)
  #results = Array(Float64, rows)
  results = Array{Float64}(undef,rows)
  for i = 0:rows - 1
    results[i + 1] = getRRCDataElement(resultHandle, i, column)
  end
  return results
end

function getNumberOfFloatingSpecies(rr)
     n = ccall(dlsym(rrlib, :getNumberOfFloatingSpecies), stdcall, Int64, (UInt,), rr)
     return n
end

function createRRCData(rrDataHandle)
    return ccall(dlsym(rrlib, :createRRCData), cdecl, UInt, (Ptr{Nothing},), rrDataHandle)
end

function getGlobalParameterIdsNew(rr)
  return unsafe_load(ccall(dlsym(rrlib, :getGlobalParameterIds), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr))
end

function getGlobalParameterIdsNoLoad(rr)
  return ccall(dlsym(rrlib, :getGlobalParameterIds), cdecl, Ptr{RRStringArray}, (Ptr{Nothing},), rr)
end

function addSpecies(rr::Ptr{Nothing}, sid::String, compartment::String, initialAmount::Float64, substanceUnit::String, regen::Bool)
  status = false
  if regen == true
    status = ccall(Libdl.dlsym(rrlib, :addSpecies), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Ptr{UInt8}, Cdouble, Ptr{UInt8}), rr, sid, compartment, initialAmount, substanceUnit)
  else
    status = ccall(Libdl.dlsym(rrlib, :addSpeciesNoRegen), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Ptr{UInt8}, Cdouble, Ptr{UInt8}), rr, sid, compartment, initialAmount, substanceUnit)
  end
  if status == false
    error(getLastError())
  end
end

function removeSpecies(rr::Ptr{Nothing}, sid::String, regen::Bool)
  status = false
  if regen == true
    status = ccall(Libdl.dlsym(rrlib, :removeSpecies), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}), rr, sid)
  else
    status = ccall(Libdl.dlsym(rrlib, :removeSpeciesNoRegen), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}), rr, sid)
  end
  if status == false
    error(getLastError())
  end
end

function addCompartment(rr, cid::String, initVolume::Float64, regen::Bool)
  status = false
  if regen == true
    status = ccall(dlsym(rrlib, :addCompartment), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Cdouble), rr, cid, initVolume)
  else
    status = ccall(dlsym(rrlib, :addCompartmentNoRegen), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Cdouble), rr, cid, initVolume)
  end
  if status == false
    error(getLastError())
  end
end

function addReaction(rr::Ptr{Nothing}, rid::String, reactants::Array{String}, products::Array{String}, kineticLaw::String, regen::Bool)
  numReactants = length(reactants)
  numProducts = length(products)
  status = 0
  if regen == true
    status = ccall(dlsym(rrlib, :addReaction), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Ptr{Ptr{UInt8}}, Cint, Ptr{Ptr{UInt8}}, Cint, Ptr{UInt8}), rr, rid, reactants, numReactants, products, numProducts, kineticLaw)
  else
    status = ccall(dlsym(rrlib, :addReactionNoRegen), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Ptr{Ptr{UInt8}}, Cint, Ptr{Ptr{UInt8}}, Cint, Ptr{UInt8}), rr, rid, reactants, numReactants, products, numProducts, kineticLaw)
  end
  if status == false
    error(getLastError())
  end
end

function addParameter(rr::Ptr{Nothing}, pid::String, value::Float64, forceRegen::Bool)
  status = false
  if forceRegen == true
     status = ccall(dlsym(rrlib, :addParameter), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Cdouble), rr, pid, value)
  else
    status = ccall(dlsym(rrlib, :addParameterNoRegen), cdecl, Bool, (Ptr{Nothing}, Ptr{UInt8}, Cdouble), rr, pid, value)
  end
  if status == false
    error(getLastError())
  end
end

function isModelLoaded(rr::Ptr{Nothing})
  return ccall(dlsym(rrlib, :isModelLoaded), cdecl, Int8, (Ptr{Nothing}, ), rr)
end

function getParamPromotedSBML(rr::Ptr{Nothing}, sArg::String)
  return unsafe_string(ccall(dlsym(rrlib, :getParamPromotedSBML), cdecl, Ptr{UInt8}, (Ptr{Nothing}, Ptr{UInt8}), rr, sArg))
end

end # module


text:
include("ckpt_test.jl")
include("expect_test.jl")
include("log_tests.jl")
include("stage_test.jl")

ext: jl


text:
#**
function cost_eens(eqp,ks)
    cp_tbl=cap_prob_table(eqp)#make capacity probability table
    eens_all=[]#Create eens array
    eens=0.0

    for i=1:length(cp_tbl[:,1])#loop through rows of cpt
        ratio_curt=cp_tbl[i,1]/eqp.mva#find PU curtailment ratio
        diff=wind_module.wind_profs[eqp.wnd].pu.-ratio_curt#find closest PU of wind power series to PU curtail ratio
        #i_min=argmin(sqrt.((diff[:]).^2))diff[5240]
        i_min=argmin(abs.((diff[:])))
        #i_min=argmin(diff[:])
        if ratio_curt>=1#check if curt ratio is at or above full power and set ce=curtailed energy to 0
            ce=wind_module.wind_profs[eqp.wnd].ce[1]
        elseif ratio_curt<=0#check if curt ratio is at or below zero power and set ce to max
            ce=wind_module.wind_profs[eqp.wnd].ce[length(wind_module.wind_profs[eqp.wnd].ce)]
        #interpolation is not needed it is already accurate to several decimal points
        #=elseif i_min < length(diff) && diff[i_min]<0#if curt ratio is a mid point interpolate ce
            ce=interpolate(ratio_curt,eqp.wnd.pu[i_min],eqp.wnd.pu[i_min+1],eqp.wnd.ce[i_min],eqp.wnd.ce[i_min+1])
        elseif i_min > 1 && diff[i_min]>0
            ce=interpolate(ratio_curt,eqp.wnd.pu[i_min-1],eqp.wnd.pu[i_min],eqp.wnd.ce[i_min-1],eqp.wnd.ce[i_min])=#
        else#if exact match occurs
            ce=wind_module.wind_profs[eqp.wnd].ce[i_min]
        end

        push!(eens_all, ce*eqp.mva*cp_tbl[i,2])#multiply PU curtailed energy with max power and availability, then store
    end
    eens=sum(eens_all)*npv_years()*ks.E_op#sum all eens and multiply by cost factors
    return eens
end

#The calculation of equipment level capacity probability table **
#**
function cap_prob_table(eqp)
    #Calculate Availability of eqiupment
    A_eqp=1.0/(1.0+eqp.relia.fr*(eqp.relia.mttr*30.0*24.0/8760.0))
    #Create combinatorial matrix of 0s and 1s
    clms=trunc(Int,eqp.num)
    rows=trunc(Int, 2.0^clms)
    empty_tbl=blank_table(rows,clms)
    #Create blank power and availability tables
    PWR_tbl=zeros(Float32,rows,1)
    AVL_tbl=ones(Float32,rows,1)
    #Set powers and availabilities by looping through the CPT
    for k=1:clms
        for j=1:rows
        #if 1 the equipment is functional and the power is added to total
        #the availability is multiplied
            if trunc(Int,empty_tbl[j,k])==1
                AVL_tbl[j]=AVL_tbl[j]*A_eqp
                PWR_tbl[j]=min(eqp.mva,PWR_tbl[j]+eqp.elec.mva)
        #if 0 the equipment is broken and no power is transmitted
            else
                AVL_tbl[j]=AVL_tbl[j]*(1-A_eqp)
            end
          end
      end
    #all unique power levels are extracted
    tbl_c1=unique(PWR_tbl)
    tbl_c2=zeros(Float32,length(tbl_c1),1)
    for k=1:length(tbl_c1)
      for j=1:length(AVL_tbl)
    #Availabilities are summed for common power levels
          if PWR_tbl[j]==tbl_c1[k]
              tbl_c2[k]=tbl_c2[k]+AVL_tbl[j]
          end
      end
    end
    #Checks if probability sums to 1 else error is thrown
    if sum(tbl_c2) > 1.0001 || sum(tbl_c2) < 0.9999
        println("sum is: "*string(sum(tbl_c2)))
        #error("probability does not sum to 1")
    elseif maximum(tbl_c1) > eqp.mva && minimum(tbl_c1) > 1
        #error("power is not correct")
    else
      return [tbl_c1 tbl_c2]
    end
end

#creates a blank capacity probability table **
#**
function blank_table(rows,clms)
    XFM_CBL=trunc.(Int8,zeros(rows,clms))
#=create all combinations ie
transpose(
11101000
11010100
10110010
)
=#
    round=1
    k=1
    multi=1
    while round<=clms
      while k<rows
        while k<=(multi*2^(clms-round))
          XFM_CBL[k,round]=1
          k=k+1
        end
        multi=multi+2
        k=k+2^(clms-round)
      end
      round=round+1
      k=1
      multi=1
    end
    return XFM_CBL
end

#linearly interpolates 2 points of graph **
#**
function interpolate(true_x,min_x,max_x,min_y,max_y)
    slope=(max_y-min_y)/(max_x-min_x)
    b=min_y-slope*min_x
    true_y=slope*true_x+b
    return true_y
end


text:
module EasyStream

using CSV
using DataFrames

include("connector.jl")
include("event.jl")

include("modifiers.jl")

include("stream.jl")

include("others.jl")

include("datasets.jl")

include("drifts.jl")

export clear!, reset!

end # module


text:
using NODEData
using Test
using OrdinaryDiffEq

@testset "NODEDataloader" begin

    f(u,p,t) = 1.01*u
    u0 = 1/2
    tspan = (0.0,10.0)
    prob = ODEProblem(f,u0,tspan)
    sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8)

    # interpolate
    data = NODEDataloader(sol, 20, dt=0.2)

    @test size(data[1][2])[end] == 20
    @test size(data[1][2])[end] == 20
    @test data[1][1] == 0:0.2:3.8
    @test data[1][2][2:end] == data[2][2][1:end-1]
    @test data[end-1][2][2:end] == data[end][2][1:end-1]

    # valid set

    train, valid = NODEDataloader(sol, 20, dt=0.2, valid_set=0.2)

    # original data
    data = NODEDataloader(sol, 10)

    @test size(data[1][2])[end] == 10
    @test data[1][1] == sol.t[1:10]
    @test data[1][2] == Array(sol)[1:10]
    @test data[1][2][2:end] == data[2][2][1:end-1]
    @test data[end-1][2][2:end] == data[end][2][1:end-1]

end

# TBD: better tests
@testset "LargeNODEDataloader" begin

    f(u,p,t) = 1.01*u
    u0 = 1/2
    tspan = (0.0,50.0)
    prob = ODEProblem(f,u0,tspan)
    sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8)

    # interpolate
    data = LargeNODEDataloader(sol, 10, 5, "test", dt=0.2)

    @test (data[1])[1][1] == 0.0:0.2:0.8

    delete(data)

    data, valid = LargeNODEDataloader(sol, 10, 5, "test", dt=0.2, valid_set=true)

    @test typeof(valid[1][2]) <: AbstractArray

    delete(data)
end


text:
"""
    WindowsPath()
    WindowsPath(str)

Represents a windows path (e.g., `C:\\User\\Documents`)
"""
struct WindowsPath <: AbstractPath
    segments::Tuple{Vararg{String}}
    root::String
    drive::String
    separator::String

    function WindowsPath(
        segments::Tuple, root::String, drive::String, separator::String=WIN_PATH_SEPARATOR
    )
        return new(Tuple(Iterators.filter(!isempty, segments)), root, drive, separator)
    end
end

function _win_splitdrive(fp::String)
    m = match(r"^([^\\]+:|\\\\[^\\]+\\[^\\]+|\\\\\?\\UNC\\[^\\]+\\[^\\]+|\\\\\?\\[^\\]+:|)(.*)$", fp)
    String(m.captures[1]), String(m.captures[2])
end

WindowsPath() = WindowsPath(tuple(), "", "")

function WindowsPath(str::AbstractString)
    if isempty(str)
        return WindowsPath(tuple("."), "", "")
    end

    if startswith(str, "\\\\?\\")
        error("The \\\\?\\ prefix is currently not supported.")
    end

    str = replace(str, POSIX_PATH_SEPARATOR => WIN_PATH_SEPARATOR)

    if startswith(str, "\\\\")
        error("UNC paths are currently not supported.")
    elseif startswith(str, "\\")
        tokenized = split(str, WIN_PATH_SEPARATOR)

        return WindowsPath(tuple(String.(tokenized[2:end])...), WIN_PATH_SEPARATOR, "")
    elseif occursin(":", str)
        l_drive, l_path = _win_splitdrive(str)

        tokenized = split(l_path, WIN_PATH_SEPARATOR)

        l_root = isempty(tokenized[1]) ? WIN_PATH_SEPARATOR : ""

        if isempty(tokenized[1])
            tokenized = tokenized[2:end]
        end

        if !isempty(l_drive) || !isempty(l_root)
            tokenized = tuple(tokenized...)
        end

        return WindowsPath(tuple(String.(tokenized)...), l_root, l_drive)
    else
        tokenized = split(str, WIN_PATH_SEPARATOR)

        return WindowsPath(tuple(String.(tokenized)...), "", "")
    end
end

function Base.:(==)(a::WindowsPath, b::WindowsPath)
    return lowercase.(a.segments) == lowercase.(b.segments) &&
        lowercase(a.root) == lowercase(b.root) &&
        lowercase(a.drive) == lowercase(b.drive)
end

ispathtype(::Type{WindowsPath}, str::AbstractString) = Sys.iswindows()

function Base.show(io::IO, fp::WindowsPath)
    print(io, "p\"")
    if isabs(fp)
        print(io, replace(fp.anchor, "\\" => "/"))
    end
    print(io, join(fp.segments, "/"))
    print(io, "\"")
end

function isabs(fp::WindowsPath)
    return !isempty(fp.drive) || !isempty(fp.root)
end


text:
using Test,BayesianNetworkRegression,LinearAlgebra,Distributions
using CSV,DataFrames

function symmetrize_matrices(X)
    X_new = Array{Array{Int8,2},1}(undef,0)
    for i in 1:size(X,1)
        B = convert(Matrix, reshape(X[i], 4, 4))
        push!(X_new,Symmetric(B))
    end
    X = X_new
end

X = [[0, 1, 0, 1,
     1, 0, 1, 1,
     0, 1, 0, 0,
     0, 1, 0, 0],
    [0, 1, 1, 1,
     1, 0, 1, 1,
     1, 1, 0, 0,
     1, 1, 0, 0],
    [0, 0, 1, 0,
     0, 0, 1, 1,
     1, 1, 0, 0,
     0, 1, 0, 0],
    [0, 0, 1, 0,
     0, 0, 1, 1,
     1, 1, 0, 1,
     0, 1, 1, 0]]

Z = symmetrize_matrices(X)

y = ones(size(Z[1],1))*12 + rand(Normal(0,2),size(Z[1],1))

η  = 1.01
ζ  = 1.0
ι  = 1.0
R  = 5
aΔ = 0.0
bΔ = 0.0
V = size(Z,1)
q = floor(Int,V*(V-1)/2)
n = size(Z,1)
ν = 12

@testset "InitTests" begin
    X_new, θ, D, πᵥ, Λ, Δ, ξ, M, u, μ, τ², γ = BayesianNetworkRegression.init_vars!(Z, η, ζ, ι, R, aΔ, bΔ, ν, V,true)

    @test size(X_new) == (n,q)
    @test size(D[1]) == (q,q)
    @test size(πᵥ[1]) == (R,3)
    @test size(Λ[1]) == (R,R)
    @test issubset(ξ[1],[0,1])
    @test size(M[1]) == (R,R)
    @test size(u[1]) == (R,V)
    @test size(γ[1]) == (q,)
end

@testset "Sim tests" begin
    R  = 5
    V = 20
    nburn = 200
    nsamp = 200

    data_in = DataFrame(CSV.File(joinpath(@__DIR__, "data", "test1.csv")))

    X = Matrix(data_in[:,1:190])
    y = data_in[:,191]

    result = GenerateSamples!(X, y, R, nburn=nburn,nsamples=nsamp, V=V, aΔ=1.0, bΔ=1.0,ν=10 ,ι=1.0,ζ=1.0,x_transform=false)

    @test size(result.Gammas) == (nsamp,)
    @test size(result.Xis) == (nsamp,)
    @test size(result.us) == (nsamp,)

    @test size(result.us[1]) == (R,V)
end


text:
include("dependencies_for_runtests.jl")
using Oceananigans.Models.HydrostaticFreeSurfaceModels
import Oceananigans.Models.HydrostaticFreeSurfaceModels: SplitExplicitFreeSurface
import Oceananigans.Models.HydrostaticFreeSurfaceModels: SplitExplicitState, SplitExplicitAuxiliary, SplitExplicitSettings, split_explicit_free_surface_substep!

@testset "Split-Explicit Dynamics" begin

    for arch in archs
        topology = (Periodic, Periodic, Bounded)

        Nx, Ny, Nz = 128, 64, 16
        Lx = Ly = Lz = 2π

        grid = RectilinearGrid(arch, topology = topology, size = (Nx, Ny, Nz), x = (0, Lx), y = (0, Ly), z = (-Lz, 0), halo=(1, 1, 1))

        sefs = SplitExplicitFreeSurface(grid)

        sefs.η .= 0.0

        @testset " One timestep test " begin
            state = sefs.state
            auxiliary = sefs.auxiliary
            U, V, η̅, U̅, V̅ = state.U, state.V, state.η̅, state.U̅, state.V̅
            Gᵁ, Gⱽ = auxiliary.Gᵁ, auxiliary.Gⱽ
            Hᶠᶜ, Hᶜᶠ = sefs.auxiliary.Hᶠᶜ, sefs.auxiliary.Hᶜᶠ
            g = sefs.gravitational_acceleration

            Hᶠᶜ .= 1 / g
            Hᶜᶠ .= 1 / g
            η = sefs.η
            velocity_weight = 0.0
            free_surface_weight = 0.0
            Δτ = 1.0

            η₀(x, y) = sin(x)
            set!(η, η₀)
            U₀(x, y) = 0.0
            set!(U, U₀)
            V₀(x, y) = 0.0
            set!(V, V₀)

            η̅ .= 0.0
            U̅ .= 0.0
            V̅ .= 0.0
            Gᵁ .= 0.0
            Gⱽ .= 0.0

            split_explicit_free_surface_substep!(η, sefs.state, sefs.auxiliary, sefs.settings, arch, grid, g, Δτ, 1)
            U_computed = Array(U.data.parent)[2:Nx+1, 2:Ny+1]
            U_exact = (reshape(-cos.(grid.xᶠᵃᵃ), (length(grid.xᶜᵃᵃ), 1)).+reshape(0 * grid.yᵃᶜᵃ, (1, length(grid.yᵃᶜᵃ))))[2:Nx+1, 2:Ny+1]

            @test maximum(abs.(U_exact - U_computed)) < 1e-3
        end

        @testset "Multi-timestep test " begin
            state = sefs.state
            auxiliary = sefs.auxiliary
            U, V, η̅, U̅, V̅ = state.U, state.V, state.η̅, state.U̅, state.V̅
            Gᵁ, Gⱽ = auxiliary.Gᵁ, auxiliary.Gⱽ
            g = sefs.gravitational_acceleration
            sefs.auxiliary.Hᶠᶜ .= 1 / g
            sefs.auxiliary.Hᶜᶠ .= 1 / g
            η = sefs.η
            velocity_weight = 0.0
            free_surface_weight = 0.0

            T = 2π
            Δτ = 2π / maximum([Nx, Ny]) * 5e-2 # the last factor is essentially the order of accuracy
            Nt = floor(Int, T / Δτ)
            Δτ_end = T - Nt * Δτ

            # set!(η, f(x,y))
            η₀(x, y) = sin(x)
            set!(η, η₀)
            U₀(x, y) = 0.0
            set!(U, U₀)
            V₀(x, y) = 0.0
            set!(V, V₀)

            η̅ .= 0.0
            U̅ .= 0.0
            V̅ .= 0.0
            Gᵁ .= 0.0
            Gⱽ .= 0.0

            for i in 1:Nt
                split_explicit_free_surface_substep!(η, sefs.state, sefs.auxiliary, sefs.settings, arch, grid, g, Δτ, 1)
            end
            # + correction for exact time
            split_explicit_free_surface_substep!(η, sefs.state, sefs.auxiliary, sefs.settings, arch, grid, g, Δτ_end, 1)

            U_computed = Array(U.data.parent)[2:Nx+1, 2:Ny+1]
            η_computed = Array(η.data.parent)[2:Nx+1, 2:Ny+1]
            set!(η, η₀)
            set!(U, U₀)
            U_exact = Array(U.data.parent)[2:Nx+1, 2:Ny+1]
            η_exact = Array(η.data.parent)[2:Nx+1, 2:Ny+1]

            @test maximum(abs.(U_computed - U_exact)) < 1e-3
            @test maximum(abs.(η_computed - η_exact)) < 1e-6
        end

        @testset "Averaging / Do Nothing test " begin
            state = sefs.state
            auxiliary = sefs.auxiliary
            U, V, η̅, U̅, V̅ = state.U, state.V, state.η̅, state.U̅, state.V̅
            Gᵁ, Gⱽ = auxiliary.Gᵁ, auxiliary.Gⱽ

            g = sefs.gravitational_acceleration
            sefs.auxiliary.Hᶠᶜ .= 1 / g
            sefs.auxiliary.Hᶜᶠ .= 1 / g
            η = sefs.η
            velocity_weight = 0.0
            free_surface_weight = 0.0

            Δτ = 2π / maximum([Nx, Ny]) * 5e-2 # the last factor is essentially the order of accuracy

            # set!(η, f(x,y))
            η_avg = 1.0
            U_avg = 2.0
            V_avg = 3.0
            η₀(x, y) = η_avg
            set!(η, η₀)
            U₀(x, y) = U_avg
            set!(U, U₀)
            V₀(x, y) = V_avg
            set!(V, V₀)

            η̅ .= 0.0
            U̅ .= 0.0
            V̅ .= 0.0
            Gᵁ .= 0.0
            Gⱽ .= 0.0
            settings = sefs.settings

            for i in 1:settings.substeps
                split_explicit_free_surface_substep!(η, sefs.state, sefs.auxiliary, sefs.settings, arch, grid, g, Δτ, 1)
            end

            U_computed = Array(U.data.parent)[2:Nx+1, 2:Ny+1]
            V_computed = Array(V.data.parent)[2:Nx+1, 2:Ny+1]
            η_computed = Array(η.data.parent)[2:Nx+1, 2:Ny+1]

            U̅_computed = Array(U̅.data.parent)[2:Nx+1, 2:Ny+1]
            V̅_computed = Array(V̅.data.parent)[2:Nx+1, 2:Ny+1]
            η̅_computed = Array(η̅.data.parent)[2:Nx+1, 2:Ny+1]

            tolerance = eps(100.0)

            @test maximum(abs.(U_computed .- U_avg)) < tolerance
            @test maximum(abs.(η_computed .- η_avg)) < tolerance
            @test maximum(abs.(V_computed .- V_avg)) < tolerance

            @test maximum(abs.(U̅_computed .- U_avg)) < tolerance
            @test maximum(abs.(η̅_computed .- η_avg)) < tolerance
            @test maximum(abs.(V̅_computed .- V_avg)) < tolerance
        end

        @testset "Complex Multi-Timestep " begin
            # Test 3: Testing analytic solution to
            # ∂ₜη + ∇⋅U⃗ = 0
            # ∂ₜU⃗ + ∇η  = G⃗
            kx = 2
            ky = 3
            ω = sqrt(kx^2 + ky^2)
            T = 2π / ω / 3 * 2
            Δτ = 2π / maximum([Nx, Ny]) * 1e-2 # error mostly spatially dependent, except in the averaging
            Nt = floor(Int, T / Δτ)
            Δτ_end = T - Nt * Δτ

            sefs = SplitExplicitFreeSurface(grid)
            state = sefs.state
            auxiliary = sefs.auxiliary
            U, V, η̅, U̅, V̅ = state.U, state.V, state.η̅, state.U̅, state.V̅
            Gᵁ, Gⱽ = auxiliary.Gᵁ, auxiliary.Gⱽ
            η = sefs.η
            g = sefs.gravitational_acceleration
            sefs.auxiliary.Hᶠᶜ .= 1 / g # to make life easy
            sefs.auxiliary.Hᶜᶠ .= 1 / g # to make life easy

            # set!(η, f(x,y)) k^2 = ω^2
            gu_c = 1.0
            gv_c = 2.0
            η₀(x, y) = sin(kx * x) * sin(ky * y) + 1
            set!(η, η₀)

            η_mean_before = mean(Array(interior(η)))

            U .= 0.0 # so that ∂ᵗη(t=0) = 0.0
            V .= 0.0 # so that ∂ᵗη(t=0) = 0.0
            η̅ .= 0.0
            U̅ .= 0.0
            V̅ .= 0.0
            Gᵁ .= gu_c
            Gⱽ .= gv_c

            # overwrite weights
            tmp = ones(Nt + 1) ./ Nt # since taking Nt+1 timesteps
            tmp[end] = Δτ_end / T # since last timestep is different
            velocity_weights = Tuple(tmp)
            free_surface_weights = Tuple(tmp) # since taking Nt+1 timesteps

            settings = SplitExplicitSettings(Nt + 1, velocity_weights, free_surface_weights)
            sefs = sefs(settings)

            for i in 1:Nt
                split_explicit_free_surface_substep!(η, sefs.state, sefs.auxiliary, sefs.settings, arch, grid, g, Δτ, i)
            end
            # + correction for exact time
            split_explicit_free_surface_substep!(η, sefs.state, sefs.auxiliary, sefs.settings, arch, grid, g, Δτ_end, Nt + 1)

            η_mean_after = mean(Array(interior(η)))

            tolerance = eps(10.0)
            @test abs(η_mean_after - η_mean_before) < tolerance

            η_computed = Array(η.data.parent)[2:Nx+1, 2:Ny+1]
            U_computed = Array(U.data.parent)[2:Nx+1, 2:Ny+1]
            V_computed = Array(V.data.parent)[2:Nx+1, 2:Ny+1]

            η̅_computed = Array(η̅.data.parent)[2:Nx+1, 2:Ny+1]
            U̅_computed = Array(U̅.data.parent)[2:Nx+1, 2:Ny+1]
            V̅_computed = Array(V̅.data.parent)[2:Nx+1, 2:Ny+1]

            set!(η, η₀)

            # ∂ₜₜ(η) = Δη
            η_exact = cos(ω * T) * (Array(η.data.parent)[2:Nx+1, 2:Ny+1] .- 1) .+ 1

            U₀(x, y) = kx * cos(kx * x) * sin(ky * y) # ∂ₜU = - ∂x(η), since we know η
            set!(U, U₀)
            U_exact = -(sin(ω * T) * 1 / ω) .* Array(U.data.parent)[2:Nx+1, 2:Ny+1] .+ gu_c * T

            V₀(x, y) = ky * sin(kx * x) * cos(ky * y) # ∂ₜV = - ∂y(η), since we know η
            set!(V, V₀)
            V_exact = -(sin(ω * T) * 1 / ω) .* Array(V.data.parent)[2:Nx+1, 2:Ny+1] .+ gv_c * T

            η̅_exact = (sin(ω * T) / ω - sin(ω * 0) / ω) / T * (Array(η.data.parent)[2:Nx+1, 2:Ny+1] .- 1) .+ 1
            U̅_exact = (cos(ω * T) * 1 / ω^2 - cos(ω * 0) * 1 / ω^2) / T * Array(U.data.parent)[2:Nx+1, 2:Ny+1] .+ gu_c * T / 2
            V̅_exact = (cos(ω * T) * 1 / ω^2 - cos(ω * 0) * 1 / ω^2) / T * Array(V.data.parent)[2:Nx+1, 2:Ny+1] .+ gv_c * T / 2

            tolerance = 1e-2

            @test maximum(abs.(U_computed - U_exact)) / maximum(abs.(U_exact)) < tolerance
            @test maximum(abs.(V_computed - V_exact)) / maximum(abs.(V_exact)) < tolerance
            @test maximum(abs.(η_computed - η_exact)) / maximum(abs.(η_exact)) < tolerance

            @test maximum(abs.(U̅_computed - U̅_exact)) < tolerance
            @test maximum(abs.(V̅_computed - V̅_exact)) < tolerance
            @test maximum(abs.(η̅_computed - η̅_exact)) < tolerance
        end
    end # end of architecture loop

end # end of testset loop


text:
lockedEntityEditingFields = ["x", "y", "width", "height"]
lockedDecalEditingFields = ["x", "y", "scaleX", "scaleY", "texture"]
lastPropertyWindow = nothing
lastPropertyWindowDestroyed = false

function spawnPropertyWindow(title::String, options::Array{Form.Option, 1}, callback::Function, lockedPositions::Array{String, 1}=String[])
    destroyPrevious = get(config, "properties_destroy_previous_window", true)
    keepPreviousPosition = get(config, "properties_keep_previous_position", true)
    alwaysOnTop = get(config, "properties_always_on_top", true)

    winX, winY = 0, 0
    winScreen = nothing

    section = Form.Section("properties", options, fieldOrder=lockedPositions)
    propertyWindow = Form.createFormWindow(title, section, callback=callback)
    @guarded signal_connect(propertyWindow, :destroy) do widget
        global lastPropertyWindowDestroyed = true
    end

    visible(propertyWindow, false)

    if keepPreviousPosition && isa(lastPropertyWindow, Gtk.GtkWindowLeaf) && !lastPropertyWindowDestroyed
        winX, winY = GAccessor.position(lastPropertyWindow)
        winScreen = GAccessor.screen(lastPropertyWindow)

        GAccessor.position(propertyWindow, winX, winY)
        GAccessor.screen(propertyWindow, winScreen)
    end

    GAccessor.transient_for(propertyWindow, window)
    GAccessor.keep_above(propertyWindow, alwaysOnTop)

    showall(propertyWindow)
    visible(propertyWindow, true)

    if destroyPrevious && isa(lastPropertyWindow, Gtk.GtkWindowLeaf)
        Gtk.destroy(lastPropertyWindow)
    end

    global lastPropertyWindow = propertyWindow
    global lastPropertyWindowDestroyed = false
end

function getTargets(x::Number, y::Number, room::Maple.Room, targetLayer::Layer, selections::Set{Tuple{String, Rectangle, Any, Number}}=Set{Tuple{String, Rectangle, Any, Number}}())
    targets = Any[]
    rect = Rectangle(x, y, 1, 1)

    if isempty(selections)
        selection = bestSelection(getSelected(room, targetLayer, rect))
        if selection !== nothing
            layer, box, target, node = selection
            push!(targets, target)
        end

    else
        base = hasSelectionAt(selections, rect, room)

        if isa(base, Entity) || isa(base, Trigger)
            push!(targets, base)

            for (layer, box, target, node) in selections
                if isa(target, Entity) || isa(target, Trigger)
                    if base.name == target.name && base.id != target.id
                        push!(targets, target)
                    end
                end
            end

        elseif isa(base, Decal)
            push!(targets, base)
            push!(targets, [
                target for (layer, box, target, node) in selections if isa(target, Decal) && target != base
            ]...)
        end
    end

    return targets
end

function displayProperties(x::Number, y::Number, room::Maple.Room, targetLayer::Layer, toolsLayer::Layer, selections::Set{Tuple{String, Rectangle, Any, Number}}=Set{Tuple{String, Rectangle, Any, Number}}())
    targets = getTargets(x, y, room, targetLayer, selections)

    if !isempty(targets)
        baseTarget = targets[1]

        if isa(baseTarget, Entity) || isa(baseTarget, Trigger)
            callback = function(data::Dict{String, Any})
                updateTarget = true

                minWidth, minHeight = minimumSize(baseTarget)
                hasWidth, hasHeight = haskey(baseTarget.data, "width"), haskey(baseTarget.data, "height")
                width, height = Int(get(data, "width", minWidth)), Int(get(data, "height", minHeight))

                if hasWidth && width < minWidth || hasHeight && height < minHeight
                    updateTarget = Ahorn.topMostAskDialog("The size specified is smaller than the recommended minimum size ($minWidth, $minHeight)\nDo you want to keep this size regardless?", lastPropertyWindow)
                end

                if updateTarget
                    History.addSnapshot!(History.RoomSnapshot("Properties", room))

                    for target in targets
                        if isa(target, Entity) || isa(target, Trigger)
                            merge!(target.data, deepcopy(data))
                        end
                    end

                    redrawLayer!(targetLayer)
                    redrawLayer!(toolsLayer)
                end
            end

            ids = join([Int(t.id) for t in targets], ", ")
            ignores = length(targets) > 1 ? String["x", "y", "width", "height", "nodes"] : String[]
            options = entityConfigOptions(baseTarget, ignores)

            if !isempty(options)
                spawnPropertyWindow("$(baseTitle) - Editing '$(baseTarget.name)' - ID: $ids", options, callback, lockedEntityEditingFields)
            end

        elseif isa(baseTarget, Decal)
            callback = function(data::Dict{String, Any})
                History.addSnapshot!(History.RoomSnapshot("Properties", room))

                for target in targets
                    if isa(target, Decal)
                        texture = hasExt(data["texture"], ".png") ? data["texture"] : data["texture"] * ".png"

                        target.x = get(data, "x", target.x)
                        target.y = get(data, "y", target.y)

                        target.texture = texture

                        target.scaleX = data["scaleX"]
                        target.scaleY = data["scaleY"]
                    end
                end

                redrawLayer!(targetLayer)
                redrawLayer!(toolsLayer)
            end

            ignores = length(targets) > 1 ? String["x", "y"] : String[]
            options = decalConfigOptions(baseTarget, ignores)

            if !isempty(options)
                spawnPropertyWindow("$(baseTitle) - Editing '$(splitext(baseTarget.texture)[1])'", options, callback, lockedDecalEditingFields)
            end
        end
    end
end


text:
testdir = dirname(@__FILE__)
ENV["PATH"] = join([joinpath(dirname(testdir), "deps", "usr", "bin"), ENV["PATH"]], Sys.iswindows() ? ";" : ":")

run(Cmd(`thrift -gen jl srvcctrl.thrift`, env=ENV))
run(Cmd(`thrift -gen jl proto_tests.thrift`, env=ENV))
println("Compiled IDLs...")

cp(joinpath(testdir, "srvcctrl_impl.jl"), joinpath(testdir, "gen-jl", "srvcctrl", "srvcctrl_impl.jl"); force=true)
cp(joinpath(testdir, "proto_tests_impl.jl"), joinpath(testdir, "gen-jl", "proto_tests", "proto_tests_impl.jl"); force=true)
println("Added service implementations...")


text:
@info "Loading Caesar tools related to Images.jl."

# using Images
# using ImageTransformations

export writevideo
export imhcatPretty, csmAnimationJoinImgs, csmAnimateSideBySide
export makeVideoFromData

"""
    $SIGNATURES

Use ffmpeg to write image sequence to video file.

Notes:
- Requires Images.jl
- https://discourse.julialang.org/t/creating-a-video-from-a-stack-of-images/646/8
"""
function writevideo(fname::AbstractString,
                    imgstack::AbstractArray{<:Colorant,3};
                    overwrite=true, fps::Int=30, options=``,
                    player::AbstractString="",
                    pix_fmt="yuv420p" )
  #
  ow = overwrite ? `-y` : `-n`
  h, w, nframes = size(imgstack)
  open(`ffmpeg
      -loglevel warning
      $ow
      -f rawvideo
      -pix_fmt rgb24
      -s:v $(h)x$(w)
      -r $fps
      -i pipe:0
      $options
      -vf "transpose=0"
      -pix_fmt $pix_fmt
      $fname`, "w") do out
    for i = 1:nframes
      write(out, convert.(RGB{N0f8}, clamp01.(imgstack[:,:,i])))
    end
  end
  if 0 < length(player)
    @async run(`$player $fname`)
  end
end

function writevideo(fname::AbstractString,
                    imgs::AbstractVector{<:AbstractArray{<:Colorant,2}};
                    overwrite=true, fps::Int=30, options=``,
                    player::AbstractString="",
                    pix_fmt="yuv420p" )
  #
  @cast imgstack[r,c,k] := imgs[k][r,c]
  writevideo(fname, imgstack, overwrite=overwrite, fps=fps, options=options, player=player, pix_fmt=pix_fmt)
end

function imhcatPretty(iml::AbstractMatrix{<:Colorant},
                      imr::AbstractMatrix{<:Colorant} )
  #
  imll = similar(iml)
  fill!(imll, RGB{N0f8}(1,1,1))

  # where to place imr
  heightratio, widthratio = size(imll,1)/size(imr,1), size(imll,2)/size(imr,2)
  minratio = 0.9*minimum([heightratio, widthratio])
  imrr = Images.imresize(imr, ratio=minratio)
  offsr = round.(Int, 0.05*[size(imll)...])
  endir = [size(imrr)...] + offsr
  imll[offsr[1]:endir[1]-1,offsr[2]:endir[2]-1] .= imrr

  hcat(iml,imll)
end

function csmAnimationJoinImgs(folderpath::AbstractString = "/tmp/caesar/csmCompound/";
                              leftname::AbstractString="csm_",
                              rightname::AbstractString="tree_",
                              bothname::AbstractString="both_",
                              ext::AbstractString="png",
                              files::AbstractVector{<:AbstractString} = readdir(folderpath),
                              nrLt::Int = filter(x->occursin(ext,x),filter(x->occursin(leftname,x), files)) |> length,
                              nrRt::Int = filter(x->occursin(ext,x),filter(x->occursin(rightname,x), files)) |> length  )
  #
  # internal thread helper function
  function threadImageSideBySide(idx)
    iml = load(joinpath(folderpath,"$(leftname)$idx.$ext"))
    imr = load(joinpath(folderpath,"$(rightname)$idx.$ext"))
    imb = imhcatPretty(iml, imr)
    # save new side by side image
    save(joinpath(folderpath,"$(bothname)$idx.$ext"), imb)
  end

  # loop over all image pairs
  allFrames = 1:minimum([nrRt,nrLt])
  THRDS = Vector{Task}(undef, allFrames[end])
  @showprogress "Joining side by side $(allFrames[end]) images" for idx in allFrames
    # threading still only single CPU, ImageMagick might lock library to single file read and write.
    threadImageSideBySide(idx)
  end
  joinpath(folderpath,"$(bothname)$(allFrames[end]).$ext")
end

"""
    $SIGNATURES

Extension of `IIF.csmAnimate` that draws the `solveTree!(...; recordhists=..)`
Bayes tree development alongside the CSM animation.

Example
-------

```julia
fg = generateCanonicalFG_Hexagonal()
tree = solveTree!(fg, recordcliqs=ls(fg))

# now generate all the video frames at default `folderpath=/tmp/caesar/csmCompound/`
csmAnimateSideBySide(tree, hists)

# and render the video using ffmpeg
run(`ffmpeg -r 10 -i /tmp/caesar/csmCompound/both_%d.png -c:v libtheora -vf fps=5 -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -q 10 /tmp/caesar/csmCompound/out.ogv`)
@async run(`totem /tmp/caesar/csmCompound/out.ogv`)
```

DevNotes
- Likely possible to use `writevideo` or something similar.
- `folderpath` not fully populated everywhere so likely not working properly yet (help requested pls)
- `tree` not strictly needed, since `autohists` already has the tree structure stored inside it.
- use `dpi` to set quality and speed.

Related

IIF.csmAnimate, Caesar.writevideo
"""
function csmAnimateSideBySide(tree::AbstractBayesTree,
                              autohists::Dict{Int, T};
                              frames::Int=100,
                              interval::Int=2,
                              dpi::Int=100,
                              rmfirst::Bool=true,
                              fsmColors::Dict{Symbol,String}=Dict{Symbol,String}(),
                              defaultColor::AbstractString="gray",
                              folderpath::AbstractString="/tmp/caesar/csmCompound/",
                              videopath = joinLogPath(autohists[collect(keys(autohists))[1]][1][4].dfg, "csmAnimate_"*string(Dates.now())),
                              encode::Bool=false,
                              fps::Int=5,
                              nvenc::Bool=false,
                              BITRATE = 2000,
                              show::Bool=false   ) where T <: AbstractVector
  #
  csmAnimate( tree,
              autohists,
              interval=interval,
              frames=frames,
              dpi=dpi,
              rmfirst=rmfirst,
              folderpath=folderpath,
              fsmColors=fsmColors,
              defaultColor=defaultColor )
  #
  csmAnimationJoinImgs(folderpath)

  # vid export to videopath
  # firstkey = collect(keys(autohists))[1]

  @info "reruns of `csmAnimate` will by default clear $folderpath and thereby remove any previous work done in that folder (including previously generated videos)."
  if encode
    cmd = if !nvenc
      # known to work properly with resolution and image size
      # `ffmpeg -r 10 -i /tmp/caesar/csmCompound/both_%d.png -c:v libtheora -vf fps=$fps -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -q 10 /tmp/caesar/csmCompound/out.ogv`
      `ffmpeg -r 10 -i $folderpath/both_%d.png -c:v libtheora -vf fps=$fps -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -q 10 $videopath.ogv`
    else
      # something about this particular call order preserves the input image resolution
      # `ffmpeg -r 10 -i /tmp/caesar/csmCompound/both_%d.png -c:v h264_nvenc -preset medium -b:v $(BITRATE)k -bufsize $(BITRATE*2)k -profile:v high -bf 3 -rc-lookahead 20 -vsync 0 -vf fps=$fps -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -pix_fmt yuv420p /tmp/caesar/csmCompound/out.mp4`
      `ffmpeg -r 10 -i $folderpath/both_%d.png -c:v h264_nvenc -preset slow -b:v $(BITRATE)k -bufsize $(BITRATE*2)k -profile:v high -rc vbr_hq -cq 1 -bf 3 -vsync 0 -pix_fmt yuv420p -vf fps=$fps -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" $videopath.mp4`
    end
    run(cmd)
    show && @async run(nvenc ? `totem $videopath.mp4` : `totem $videopath.ogv`)
  end

  @info videopath
  return videopath
end

"""
    $SIGNATURES

Helper function to assemble `Entry=>Data` into a video file.

Example

```julia
# fg object with datastore containing images on subset of variables, e.g. :HEADPOSE

makeVideoFromData("/tmp/test.avi", fg, :LEFT_CAMERA, ls(fg, tags=[:HEADPOSE;]))
```

Related

fetchDataImage
"""
function makeVideoFromData( fname::AbstractString,
                            dfg::AbstractDFG,
                            dataLabel::Symbol,
                            varSym::AbstractVector{Symbol}=ls(dfg, tags=[:POSE;]) |> sortDFG;
                            fps::Int=30,
                            options=`` )
  #
  imgs = fetchDataImage.(dfg, varSym, dataLabel)
  writevideo(fname, imgs, fps=fps, options=options)
end

#


text:
using PyCall
@pyimport graphviz as gv

function render_graph(ir::BasicBlockIR, fname)
    # graphviz
    dot = gv.Digraph() # comment = ?
    nodes_to_name = Dict{Node,String}()
    for node in ir.all_nodes
        io = IOBuffer()
        print(io, node)
        nodes_to_name[node] = String(take!(io))
    end
    for node in ir.all_nodes
        if isa(node, ValueNode)
            shape = "box"
        else
            shape = "ellipse"
        end
        if node in ir.incremental_nodes
            color = "lightblue"
        else
            color = "lightgray"
        end
        if ir.output_node == node
            @assert !(node in ir.incremental_nodes)
            color = "firebrick1"
        end
        if ir.retchange_node == node
            color = "darkolivegreen2"
        end
        dot[:node](nodes_to_name[node], nodes_to_name[node], shape=shape, color=color, style="filled")
        for parent in parents(node)
            dot[:edge](nodes_to_name[parent], nodes_to_name[node])
        end
    end
    for node in values(ir.addr_gen_nodes)
        dot[:edge](nodes_to_name[node.change_node], nodes_to_name[node], style="dashed")
    end
    dot[:render](fname, view=true)
end

max_stars_repo_name: BoltzmannBrain/Gen

max_issues_repo_name: BoltzmannBrain/Gen

max_forks_repo_name: BoltzmannBrain/Gen


text:
@testset "VariationalDense" begin
    input = gpu(rand(5, 32))
    layer = VariationalDense(5, 10, device = gpu)
    output = layer(input)
    @test size(output) == (10, 32)

    # Test gradients
    layer = VariationalDense(2, 5, device = gpu)
    i = gpu(rand(2, 4))
    y = gpu(ones(5, 4))
    grads = gradient(params(layer)) do
        ŷ = layer(i)
        return Flux.logitcrossentropy(ŷ, y)
    end
    for param in params(layer)
        @test size(param) == size(grads[param])
        @test grads[param] isa CuArray
    end
end

@testset "VariationalConv" begin
    # Test gradients
    layer = VariationalConv((5, 5), 3 => 6, relu, device = gpu)
    i = gpu(rand(32, 32, 3, 4))
    y = gpu(rand(28, 28, 6, 4))
    grads = gradient(params(layer)) do
        ŷ = layer(i)
        return Flux.logitcrossentropy(ŷ, y)
    end
    for param in params(layer)
        @test size(param) == size(grads[param])
        @test grads[param] isa CuArray
    end
end


text:
module InlineTest

@static if isdefined(Base, :Experimental) &&
             isdefined(Base.Experimental, Symbol("@optlevel"))
    Base.Experimental.@optlevel 0
end

export @testset

# from Test:
export Test,
    @test, @test_throws, @test_broken, @test_skip,
    @test_warn, @test_nowarn,
    @test_logs, @test_deprecated,
    @inferred,
    detect_ambiguities, detect_unbound_args

using Test: Test,
    @test, @test_throws, @test_broken, @test_skip,
    @test_warn, @test_nowarn,
    @test_logs, @test_deprecated,
    @inferred,
    detect_ambiguities, detect_unbound_args

const INLINE_TEST = Ref{Symbol}(:__INLINE_TEST__)
const TESTED_MODULES = Union{Module,Nothing}[]

__init__() = INLINE_TEST[] = gensym()

function get_tests(m::Module)
    inline_test::Symbol = INLINE_TEST[]
    if !isdefined(m, inline_test)
        @eval m $inline_test = (tests=[], news=[], map=Dict{Union{String,Expr},Int}())
        push!(TESTED_MODULES, m)
    end
    getfield(m, inline_test)
end

function retest end

"""
    @testset args...

Similar to `Test.@testset args...`, but the contained tests are not run
immediately, and are instead stored for later execution, triggered by
`runtests()`.
Invocations of `@testset` can be nested, but qualified invocations of
`ReTest.@testset` can't.
Internally, `@testset` expressions are converted to an equivalent of
`Test.@testset` at execution time.
"""
macro testset(args...)
    if !isdefined(__module__, :runtests)
        @eval __module__ function runtests(specs...; kwargs...)
            $retest($__module__, specs...; kwargs...)
        end
    end
    # this must take effect at compile/run time rather than parse time, e.g.
    # if the @testset if in a `if false` branch
    # TODO: test that
    quote
        push!(get_tests($__module__).news, (ts=$args, source=$(QuoteNode(__source__))))
        nothing
    end
end

end # InlineTest


text:
function create(::Type{SimpleCurveFitter}, arg0::ParametricUnivariateFunction, arg1::Vector{jdouble})
    return jcall(SimpleCurveFitter, "create", SimpleCurveFitter, (ParametricUnivariateFunction, Vector{jdouble}), arg0, arg1)
end

function with_max_iterations(obj::SimpleCurveFitter, arg0::jint)
    return jcall(obj, "withMaxIterations", SimpleCurveFitter, (jint,), arg0)
end

function with_start_point(obj::SimpleCurveFitter, arg0::Vector{jdouble})
    return jcall(obj, "withStartPoint", SimpleCurveFitter, (Vector{jdouble},), arg0)
end


text:
export iterative

# Efficient least-square solution for affine diagonal component
# using least-square formulation
# function iterative(C::SparseRadialMapComponent, ens::EnsembleState{Nx, Ne}, λ, δ) where {Nx, Ne}
#     @get C (Nx,p)
#     # Compute weights
#     ψ_off, ψ_mono, _ = weights(C, ens)
#
#     # no = size(ψ_off,1)
#     # nd = size(ψ_mono,1)
#     nx = size(ψ_off,1)+size(ψ_mono,1)+1
#     # nlog = size(dψ_mono,1)
#
#     # @assert nd==nlog "Error size of the diag and ∂k weights"
#     # @assert nx==no+nlog+1 "Error size of the weights"
#
#     # Cache for the solution
#     x = zeros(nx)
#
#     # Normalize monotone basis functions
#     μψ = mean(ψ_mono, dims=2)[1,1]
#     σψ = std(ψ_mono, dims=2, corrected=false)[1,1]
#     ψ_mono .-= μψ
#     ψ_mono ./= σψ
#
#     # Normalize off-diagonal covariates
#     σψ_off = std(ψ_off, dims = 2, corrected = false)[:,1]
#     ψ_off ./= σψ_off
#     # Solve for the off-diagonal coefficients and the constant
#     # We can use dψ_mono since it contains only one
#     ψ_at = hcat(ψ_off', ones(Ne))
#
#     # Solve least-square problem
#     # x[1:nx-1] = ψ_a' \ view(ψ_mono,1,:)
#     x0 = view(x,1:nx-1)
#     lsmr!(x0, ψ_at, view(ψ_mono,1,:), λ = λ, atol = 1e-9, btol = 1e-9)
#     # lsmr!(x0, S, view(ψ_mono,1,:), λ = λ)
#
#     @inbounds for i=1:nx-2
#     x[i] *= (-σψ/σψ_off[i])
#     end
#
#     x[nx-1] *= -σψ
#     x[nx-1] -= μψ
#
#     x[end] = √(Ne)/norm(ψ_at*(x[1:nx-1] .* vcat(σψ_off, 1.0)) .+ μψ + σψ*ψ_mono[1,:])
#     x[1:nx-1] .*= x[end]
#     return x
# end

function iterative(C::SparseRadialMapComponent, X, λ, δ)
    NxX, Ne = size(X)
    @get C (Nx,p)

    @assert NxX  == Nx "Wrong dimension of the ensemble matrix `X`"
    # Compute weights
    ψ_off, ψ_mono, _ = compute_weights(C, X)

    # no = size(ψ_off,1)
    # nd = size(ψ_mono,1)
    nx = size(ψ_off,2)+size(ψ_mono,2)+1
    # nlog = size(dψ_mono,1)

    # @assert nd==nlog "Error size of the diag and ∂k weights"
    # @assert nx==no+nlog+1 "Error size of the weights"

    # Cache for the solution
    x = zeros(nx)

    # Normalize monotone basis functions
    μψ = mean(ψ_mono, dims=1)[1,1]
    σψ = std(ψ_mono, dims=1, corrected=false)[1,1]
    ψ_mono .-= μψ
    ψ_mono ./= σψ

    # Normalize off-diagonal covariates
    σψ_off = std(ψ_off, dims = 1, corrected = false)[1,:]
    ψ_off ./= σψ_off'
    # Solve for the off-diagonal coefficients and the constant
    # We can use dψ_mono since it contains only one
    ψ_at = hcat(ψ_off, ones(Ne))

    # Solve least-square problem
    # x[1:nx-1] = ψ_a' \ view(ψ_mono,1,:)
    x0 = view(x,1:nx-1)
    lsmr!(x0, ψ_at, view(ψ_mono,:,1), λ = λ, atol = 1e-9, btol = 1e-9)
    # lsmr!(x0, S, view(ψ_mono,1,:), λ = λ)

    @inbounds for i=1:nx-2
    x[i] *= (-σψ/σψ_off[i])
    end

    x[nx-1] *= -σψ
    x[nx-1] -= μψ

    x[end] = √(Ne)/norm(ψ_at*(x[1:nx-1] .* vcat(σψ_off, 1.0)) .+ μψ + σψ*ψ_mono[:,1])
    x[1:nx-1] .*= x[end]
    return x
end