text:
# MIT License
#
# Copyright (c) 2018 Martin Biel
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
    DeterministicEquivalent

Deterministic equivalent memory structure. Stochastic program is stored as one large optimization problem. Supported by any standard `AbstractOptimizer`.

"""
struct DeterministicEquivalent{N, M, S <: NTuple{M, Scenarios}} <: AbstractStochasticStructure{N}
    decisions::Decisions{N}
    scenarios::S
    model::JuMP.Model
    proxy::NTuple{N,JuMP.Model}

    function DeterministicEquivalent(decisions::Decisions{N}, scenarios::NTuple{M, Scenarios}) where {N, M}
        M == N - 1 || error("Inconsistent number of stages $N and number of scenario types $M")
        proxy = ntuple(Val{N}()) do _
            Model()
        end
        S = typeof(scenarios)
        return new{N,M,S}(decisions, scenarios, Model(), proxy)
    end
end

function StochasticStructure(decisions::Decisions{N}, scenario_types::ScenarioTypes{M}, ::Deterministic) where {N, M}
    scenarios = ntuple(Val(M)) do i
        Vector{scenario_types[i]}()
    end
    return DeterministicEquivalent(decisions, scenarios)
end

function StochasticStructure(decisions::Decisions{N}, scenarios::NTuple{M, Vector{<:AbstractScenario}}, ::Deterministic) where {N, M}
    return DeterministicEquivalent(decisions, scenarios)
end

# Base overloads #
# ========================== #
function Base.print(io::IO, structure::DeterministicEquivalent)
    print(io, "Deterministic equivalent problem\n")
    print(io, structure.model)
end
# ========================== #

# MOI #
# ========================== #
function MOI.get(structure::DeterministicEquivalent, attr::MOI.AbstractModelAttribute)
    return MOI.get(backend(structure.model), attr)
end
function MOI.get(structure::DeterministicEquivalent, attr::MOI.AbstractVariableAttribute, index::MOI.VariableIndex)
    return MOI.get(backend(structure.model), attr, index)
end
function MOI.get(structure::DeterministicEquivalent, attr::MOI.AbstractConstraintAttribute, ci::CI)
    return MOI.get(backend(structure.model), attr, ci)
end
function MOI.get(structure::DeterministicEquivalent, attr::MOI.AbstractConstraintAttribute, ci::CI{F,S}) where {F <: SingleDecision, S}
    con_ref = ConstraintRef(structure.model, ci)
    return MOI.get(structure.model, attr, con_ref)
end
function MOI.get(structure::DeterministicEquivalent{N}, attr::ScenarioDependentModelAttribute) where N
    n = num_scenarios(structure, attr.stage)
    1 <= attr.scenario_index <= n || error("Scenario index $attr.scenario_index not in range 1 to $n.")
    if attr.attr isa MOI.ObjectiveFunction
        return get_stage_objective(structure.decisions, attr.stage, attr.scenario_index)[2]
    elseif attr.attr isa MOI.ObjectiveFunctionType
        return typeof(get_stage_objective(structure.decisions, attr.stage, attr.scenario_index)[2])
    elseif attr.attr isa MOI.ObjectiveSense
        return get_stage_objective(structure.decisions, attr.stage, attr.scenario_index)[1]
    elseif attr.attr isa MOI.ObjectiveValue || attr.attr isa MOI.DualObjectiveValue
        return MOIU.eval_variables(get_stage_objective(structure.decisions, attr.stage, attr.scenario_index)[2]) do idx
            return MOI.get(backend(structure.model), MOI.VariablePrimal(), idx)
        end
    else
        # Most attributes are shared with the deterministic equivalent
        return MOI.get(backend(structure.model), attr.attr)
    end
end
function MOI.get(structure::DeterministicEquivalent, attr::ScenarioDependentVariableAttribute, index::MOI.VariableIndex)
    n = num_scenarios(structure, attr.stage)
    1 <= attr.scenario_index <= n || error("Scenario index $attr.scenario_index not in range 1 to $n.")
    mapped_vi = mapped_index(structure, index, attr.scenario_index)
    return MOI.get(backend(structure.model), attr.attr, mapped_vi)
end
function MOI.get(structure::DeterministicEquivalent, attr::ScenarioDependentConstraintAttribute, ci::CI)
    n = num_scenarios(structure, attr.stage)
    1 <= attr.scenario_index <= n || error("Scenario index $attr.scenario_index not in range 1 to $n.")
    mapped_ci = mapped_index(structure, ci, attr.scenario_index)
    return MOI.get(backend(structure.model), attr.attr, mapped_ci)
end
function MOI.get(structure::DeterministicEquivalent, attr::ScenarioDependentConstraintAttribute, ci::CI{F,S}) where {F <: SingleDecision, S}
    n = num_scenarios(structure, attr.stage)
    1 <= attr.scenario_index <= n || error("Scenario index $attr.scenario_index not in range 1 to $n.")
    mapped_vi = mapped_index(structure, MOI.VariableIndex(ci.value), attr.scenario_index)
    mapped_ci = CI{F,S}(mapped_vi.value)
    con_ref = ConstraintRef(structure.model, mapped_ci)
    return MOI.get(structure.model, attr.attr, con_ref)
end
function MOI.get(structure::DeterministicEquivalent, attr::ScenarioDependentConstraintAttribute, ci::CI{F,S}) where {F <: MOI.SingleVariable, S}
    n = num_scenarios(structure, attr.stage)
    1 <= attr.scenario_index <= n || error("Scenario index $attr.scenario_index not in range 1 to $n.")
    mapped_vi = mapped_index(structure, MOI.VariableIndex(ci.value), attr.scenario_index)
    mapped_ci = CI{F,S}(mapped_vi.value)
    return MOI.get(backend(structure.model), attr.attr, mapped_ci)
end

function MOI.set(structure::DeterministicEquivalent, attr::MOI.Silent, flag)
    MOI.set(backend(structure.model), attr, flag)
    return nothing
end
function MOI.set(structure::DeterministicEquivalent{N}, attr::MOI.AbstractModelAttribute, value) where N
    if attr isa MOI.ObjectiveFunction
        # Get full objective+sense
        dep_obj = copy(value)
        obj_sense = objective_sense(structure.model)
        # Update first-stage objective
        set_stage_objective!(structure.decisions, 1, 1, obj_sense, value)
        # Update main objective
        for (i, sub_objective) in enumerate(structure.decisions.stage_objectives[2])
            (sense, func) = sub_objective
            if obj_sense == sense
                dep_obj += probability(structure, 2, i) * func
            else
                dep_obj -= probability(structure, 2, i) * func
            end
        end
        MOI.set(backend(structure.model), attr, dep_obj)
    elseif attr isa MOI.ObjectiveSense
        # Get full objective+sense
        prev_sense, dep_obj = get_stage_objective(structure.decisions, 1, 1)
        # Update first-stage objective
        set_stage_objective!(structure.decisions, 1, 1, value, dep_obj)
        # Update main objective (if necessary)
        if value != prev_sense
            for (i, sub_objective) in enumerate(structure.decisions.stage_objectives[2])
                (sense, func) = sub_objective
                if value == sense
                    dep_obj += probability(structure, 2, i) * func
                else
                    dep_obj -= probability(structure, 2, i) * func
                end
            end
            MOI.set(backend(structure.model), MOI.ObjectiveFunction{typeof(dep_obj)}(), dep_obj)
        end
        MOI.set(backend(structure.model), MOI.ObjectiveSense(), value)
    else
        # Most attributes are shared with the deterministic equivalent
        MOI.set(backend(structure.model), attr, value)
    end
    return nothing
end
function MOI.set(structure::DeterministicEquivalent, attr::MOI.AbstractVariableAttribute,
                 index::MOI.VariableIndex, value)
    MOI.set(backend(structure.model), attr, index, value)
    return nothing
end
function MOI.set(structure::DeterministicEquivalent, attr::MOI.AbstractConstraintAttribute,
                 ci::MOI.ConstraintIndex, value)
    con_ref = ConstraintRef(structure.model, mapped_ci)
    MOI.set(structure.model, attr.attr, con_ref, value)
    return nothing
end
function MOI.set(structure::DeterministicEquivalent{N}, attr::ScenarioDependentModelAttribute, value) where N
    if attr.attr isa MOI.ObjectiveFunction
        # Get full objective+sense
        obj_sense = objective_sense(structure.model)
        dep_obj = objective_function(structure.model)
        # Update subobjective
        (sub_sense, prev_func) = get_stage_objective(structure.model, attr.stage, attr.scenario_index, Val{N}())
        set_stage_objective!(structure.decisions, attr.stage, attr.scenario_index, sub_sense, value)
        sub_obj = jump_function(structure.model, value)
        # Update main objective
        if obj_sense == sub_sense
            dep_obj += probability(structure, attr.stage, attr.scenario_index) * (sub_obj - prev_func)
        else
            dep_obj -= probability(structure, attr.stage, attr.scenario_index) * (sub_obj - prev_func)
        end
        set_objective_function(structure.model, dep_obj)
    elseif attr.attr isa MOI.ObjectiveSense
        # Get current
        (prev_sense, func) = get_stage_objective(structure.model, attr.stage, attr.scenario_index, Val{N}())
        if value == prev_sense
            # Nothing to do
            return nothing
        end
        # Get full objective+sense
        obj_sense = objective_sense(structure.model)
        dep_obj = objective_function(structure.model)
        # Update subobjective sense
        set_stage_objective!(structure.decisions, attr.stage, attr.scenario_index, value, moi_function(func))
        # Update main objective
        if value == obj_sense
            dep_obj += 2 * probability(structure, attr.stage, attr.scenario_index) * func
        else
            dep_obj -= 2 * probability(structure, attr.stage, attr.scenario_index) * func
        end
        set_objective_function(structure.model, dep_obj)
    else
        # Most attributes are shared with the deterministic equivalent
        MOI.set(backend(structure.model), attr.attr, value)
    end
    return nothing
end
function MOI.set(structure::DeterministicEquivalent, attr::ScenarioDependentVariableAttribute,
                 index::MOI.VariableIndex, value)
    n = num_scenarios(structure, attr.stage)
    1 <= attr.scenario_index <= n || error("Scenario index $attr.scenario_index not in range 1 to $n.")
    mapped_vi = mapped_index(structure, index, attr.scenario_index)
    MOI.set(backend(structure.model), attr.attr, mapped_vi, value)
    return nothing
end
function MOI.set(structure::DeterministicEquivalent, attr::ScenarioDependentConstraintAttribute,
                 ci::CI, value)
    n = num_scenarios(structure, attr.stage)
    1 <= attr.scenario_index <= n || error("Scenario index $attr.scenario_index not in range 1 to $n.")
    mapped_ci = mapped_index(structure, ci, attr.scenario_index)
    MOI.set(backend(structure.model), attr.attr, mapped_ci, value)
    return nothing
end
function MOI.set(structure::DeterministicEquivalent, attr::ScenarioDependentConstraintAttribute,
                 ci::CI{F,S}, value) where {F <: SingleDecision, S}
    n = num_scenarios(structure, attr.stage)
    1 <= attr.scenario_index <= n || error("Scenario index $attr.scenario_index not in range 1 to $n.")
    mapped_vi = mapped_index(structure, MOI.VariableIndex(ci.value), attr.scenario_index)
    mapped_ci = CI{F,S}(mapped_vi.value)
    con_ref = ConstraintRef(structure.model, mapped_ci)
    MOI.set(structure.model, attr.attr, con_ref, value)
    return nothing
end
function MOI.set(structure::DeterministicEquivalent, attr::ScenarioDependentConstraintAttribute,
                 ci::CI{F,S}, value) where {F <: MOI.SingleVariable, S}
    n = num_scenarios(structure, attr.stage)
    1 <= attr.scenario_index <= n || error("Scenario index $attr.scenario_index not in range 1 to $n.")
    mapped_vi = mapped_index(structure, MOI.VariableIndex(ci.value), attr.scenario_index)
    mapped_ci = CI{F,S}(mapped_vi.value)
    MOI.set(backend(structure.model), attr.attr, mapped_ci, value)
    return nothing
end

function MOI.is_valid(structure::DeterministicEquivalent, index::MOI.VariableIndex, stage::Integer)
    stage == 1 || error("No scenario index specified.")
    return MOI.is_valid(backend(structure.model), index)
end
function MOI.is_valid(structure::DeterministicEquivalent, index::MOI.VariableIndex, stage::Integer, scenario_index::Integer)
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    mapped_vi = mapped_index(structure, index, scenario_index)
    return MOI.is_valid(backend(structure.model), mapped_vi)
end
function MOI.is_valid(structure::DeterministicEquivalent, ci::MOI.ConstraintIndex{F,S}, stage::Integer) where {F, S}
    stage == 1 || error("No scenario index specified.")
    return MOI.is_valid(backend(structure.model), ci)
end
function MOI.is_valid(structure::DeterministicEquivalent, ci::MOI.ConstraintIndex{F,S}, stage::Integer, scenario_index::Integer) where {F, S}
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    mapped_ci = mapped_index(structure, ci, scenario_index)
    return MOI.is_valid(backend(structure.model), mapped_ci)
end
function MOI.delete(structure::DeterministicEquivalent, indices::Vector{MOI.VariableIndex}, stage::Integer)
    stage == 1 || error("No scenario index specified.")
    JuMP.delete(structure.model, DecisionRef.(structure.model, indices))
    return nothing
end
function MOI.delete(structure::DeterministicEquivalent{N}, indices::Vector{MOI.VariableIndex}, stage::Integer, scenario_index::Integer) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    mapped_indices = map(indices) do index
        return mapped_index(structure, index, scenario_index)
    end
    JuMP.delete(structure.model, DecisionRef.(structure.model, mapped_indices))
    return nothing
end
function MOI.delete(structure::DeterministicEquivalent, ci::MOI.ConstraintIndex, stage::Integer)
    stage == 1 || error("No scenario index specified.")
    MOI.delete(backend(structure.model), ci)
    return nothing
end
function MOI.delete(structure::DeterministicEquivalent, cis::Vector{<:MOI.ConstraintIndex}, stage::Integer)
    stage == 1 || error("No scenario index specified.")
    MOI.delete(backend(structure.model), cis)
    return nothing
end
function MOI.delete(structure::DeterministicEquivalent{N}, ci::MOI.ConstraintIndex, stage::Integer, scenario_index::Integer) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    mapped_ci = mapped_index(structure, ci, scenario_index)
    MOI.delete(backend(structure.model), mapped_ci)
    return nothing
end
function MOI.delete(structure::DeterministicEquivalent{N}, cis::Vector{<:MOI.ConstraintIndex}, stage::Integer, scenario_index::Integer) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    mapped_cis = map(cis) do ci
        return mapped_index(structure, ci, scenario_index)
    end
    MOI.delete(backend(structure.model), mapped_cis)
    return nothing
end

# JuMP #
# ========================== #
function decision_dispatch(decision_function::Function,
                           structure::DeterministicEquivalent{N},
                           index::MOI.VariableIndex,
                           stage::Integer,
                           args...) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage == 1 || error("No scenario index specified.")
    dref = DecisionRef(structure.model, index)
    return decision_function(dref, args...)
end
function scenario_decision_dispatch(decision_function::Function,
                                    structure::DeterministicEquivalent{N},
                                    index::MOI.VariableIndex,
                                    stage::Integer,
                                    scenario_index::Integer,
                                    args...) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    mapped_vi = mapped_index(structure, index, scenario_index)
    dref = DecisionRef(structure.model, mapped_vi)
    return decision_function(dref, args...)
end
function decision_dispatch!(decision_function!::Function,
                            structure::DeterministicEquivalent{N},
                            index::MOI.VariableIndex,
                            stage::Integer,
                            args...) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage == 1 || error("No scenario index specified.")
    dref = DecisionRef(structure.model, index)
    decision_function!(dref, args...)
    return nothing
end
function scenario_decision_dispatch!(decision_function!::Function,
                                     structure::DeterministicEquivalent{N},
                                     index::MOI.VariableIndex,
                                     stage::Integer,
                                     scenario_index::Integer,
                                     args...) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    mapped_vi = mapped_index(structure, index, scenario_index)
    dref = DecisionRef(structure.model, mapped_vi)
    decision_function!(dref, args...)
    return nothing
end

function JuMP.fix(structure::DeterministicEquivalent{N}, index::MOI.VariableIndex, stage::Integer, val::Number) where N
    dref = DecisionRef(structure.model, index)
    fix(dref, val)
    return nothing
end
function JuMP.fix(structure::DeterministicEquivalent{N}, index::MOI.VariableIndex, stage::Integer, scenario_index::Integer, val::Number) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    # Fix mapped decision
    mapped_vi = mapped_index(structure, index, scenario_index)
    dref = DecisionRef(structure.model, mapped_vi)
    fix(dref, val)
    return nothing
end
function JuMP.unfix(structure::DeterministicEquivalent{N}, index::MOI.VariableIndex, stage::Integer) where N
    dref = DecisionRef(structure.model, index)
    unfix(dref)
    return nothing
end
function JuMP.unfix(structure::DeterministicEquivalent{N}, index::MOI.VariableIndex, stage::Integer, scenario_index::Integer) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    # Unfix mapped decision
    mapped_vi = mapped_index(structure, index, scenario_index)
    dref = DecisionRef(structure.model, mapped_vi)
    unfix(dref)
    return nothing
end

function JuMP.set_objective_sense(structure::DeterministicEquivalent, stage::Integer, sense::MOI.OptimizationSense)
    if stage == 1
        # Changing the first-stage sense modifies the whole objective as usual
        MOI.set(structure, MOI.ObjectiveSense(), sense)
    else
        # Every sub-objective in the given stage should be changed
        for scenario_index in 1:num_scenarios(structure, stage)
            attr = ScenarioDependentModelAttribute(stage, scenario_index, MOI.ObjectiveSense())
            MOI.set(structure, attr, sense)
        end
    end
    return nothing
end

function JuMP.objective_function_type(structure::DeterministicEquivalent)
    return jump_function_type(structure.model,
                              MOI.get(structure, MOI.ObjectiveFunctionType()))
end
function JuMP.objective_function_type(structure::DeterministicEquivalent{N}, stage::Integer, scenario_index::Integer) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    attr = ScenarioDependentModelAttribute(stage, scenario_index, MOI.ObjectiveFunctionType())
    return jump_function_type(structure.model,
                              MOI.get(structure, attr))
end

function JuMP.objective_function(structure::DeterministicEquivalent, FunType::Type{<:AbstractJuMPScalar})
    MOIFunType = moi_function_type(FunType)
    func = MOI.get(structure,
                   MOI.ObjectiveFunction{MOIFunType}())::MOIFunType
    return JuMP.jump_function(structure, 1, func)
end
function JuMP.objective_function(structure::DeterministicEquivalent{N}, stage::Integer, FunType::Type{<:AbstractJuMPScalar}) where N
    if stage == 1
        (sense, obj::FunType) = get_stage_objective(structure.model, 1, Val{N}())
        return obj
    else
        return objective_function(structure.proxy, FunType)
    end
end
function JuMP.objective_function(structure::DeterministicEquivalent{N},
                                 stage::Integer,
                                 scenario_index::Integer,
                                 FunType::Type{<:AbstractJuMPScalar}) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    MOIFunType = moi_function_type(FunType)
    attr = ScenarioDependentModelAttribute(stage, scenario_index, MOI.ObjectiveFunction{MOIFunType}())
    func = MOI.get(structure, attr)::MOIFunType
    return JuMP.jump_function(structure, stage, scenario_index, func)
end

function JuMP._moi_optimizer_index(structure::DeterministicEquivalent, index::VI)
    return decision_index(backend(structure.model), index)
end
function JuMP._moi_optimizer_index(structure::DeterministicEquivalent, index::VI, scenario_index::Integer)
    mapped_vi = mapped_index(structure, index, scenario_index)
    return decision_index(backend(structure.model), mapped_vi)
end
function JuMP._moi_optimizer_index(structure::DeterministicEquivalent, ci::CI)
    return decision_index(backend(structure.model), ci)
end
function JuMP._moi_optimizer_index(structure::DeterministicEquivalent, ci::CI{F,S}) where {F <: SingleDecision, S}
    inner = mapped_constraint(structure.decisions, ci)
    inner.value == 0 && error("Constraint $ci not properly mapped.")
    return decision_index(backend(structure.model), inner)
end
function JuMP._moi_optimizer_index(structure::DeterministicEquivalent, ci::CI, scenario_index::Integer)
    mapped_ci = mapped_index(structure, ci, scenario_index)
    return decision_index(backend(structure.model), mapped_ci)
end
function JuMP._moi_optimizer_index(structure::DeterministicEquivalent, ci::CI{F,S}, scenario_index::Integer) where {F <: SingleDecision, S}
    mapped_vi = mapped_index(structure, MOI.VariableIndex(ci.value), scenario_index)
    mapped_ci = CI{F,S}(mapped_vi.value)
    inner = mapped_constraint(structure.decisions, mapped_ci)
    inner.value == 0 && error("Constraint $mapped_ci not properly mapped.")
    return decision_index(backend(structure.model), inner)
end

function JuMP.set_objective_coefficient(structure::DeterministicEquivalent{N}, index::VI, var_stage::Integer, stage::Integer, coeff::Real) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    var_stage <= stage || error("Can only modify coefficient in current stage of decision or subsequent stages from where decision is taken.")
    if var_stage == 1 && stage == 1
        # Use temporary model to apply modification
        obj = get_stage_objective(structure.model, 1, Val{N}())[2]
        moi_obj = moi_function(obj)
        m = Model()
        MOI.set(backend(m), MOI.ObjectiveFunction{typeof(moi_obj)}(), moi_obj)
        dref = DecisionRef(m, index)
        set_objective_coefficient(m, dref, coeff)
        obj = objective_function(m)
        F = moi_function_type(typeof(obj))
        # Modify full objective
        MOI.set(structure, MOI.ObjectiveFunction{F}(), moi_function(obj))
    elseif (var_stage == 1 && stage > 1) || var_stage > 1
        for scenario_index in 1:num_scenarios(structure, stage)
            # Use temporary model to apply modification
            obj = get_stage_objective(structure.model, stage, scenario_index, Val{N}())[2]
            moi_obj = moi_function(obj)
            m = Model()
            MOI.set(backend(m), MOI.ObjectiveFunction{typeof(moi_obj)}(), moi_obj)
            dref = DecisionRef(m, index)
            set_objective_coefficient(m, dref, coeff)
            obj = objective_function(m)
            attr = ScenarioDependentModelAttribute(stage, scenario_index, MOI.ObjectiveFunction{typeof(obj)}())
            MOI.set(structure, attr, obj)
        end
    end
    return nothing
end
function JuMP.set_objective_coefficient(structure::DeterministicEquivalent{N}, index::VI, var_stage::Integer, stage::Integer, scenario_index::Integer, coeff::Real) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    if var_stage == 1
        # Use temporary model to apply modification
        obj = get_stage_objective(structure.model, stage, scenario_index, Val{N}())[2]
        moi_obj = moi_function(obj)
        m = Model()
        MOI.set(backend(m), MOI.ObjectiveFunction{typeof(moi_obj)}(), moi_obj)
        dref = DecisionRef(m, index)
        set_objective_coefficient(m, dref, coeff)
        obj = objective_function(m)
        F = moi_function_type(typeof(obj))
        attr = ScenarioDependentModelAttribute(stage, scenario_index, MOI.ObjectiveFunction{F}())
        MOI.set(structure, attr, moi_function(obj))
    else
        # Use temporary model to apply modification
        sense, obj = get_stage_objective(structure.model, stage, scenario_index, Val{N}())
        moi_obj = moi_function(obj)
        m = Model()
        MOI.set(backend(m), MOI.ObjectiveFunction{typeof(moi_obj)}(), moi_obj)
        mapped_vi = mapped_index(structure, index, scenario_index)
        dref = DecisionRef(m, mapped_vi)
        set_objective_coefficient(m, dref, coeff)
        obj = objective_function(m)
        set_stage_objective!(structure.decisions, stage, scenario_index, sense, moi_function(obj))
        # Set coefficient of mapped second-stage variable
        dref = DecisionRef(structure.model, mapped_vi)
        set_objective_coefficient(structure.model, dref, probability(structure, stage, scenario_index) * coeff)
    end
    return nothing
end

function JuMP.set_normalized_coefficient(structure::DeterministicEquivalent,
                                         ci::CI{F,S},
                                         index::VI,
                                         value) where {T, F <: Union{AffineDecisionFunction{T}, QuadraticDecisionFunction{T}}, S}
    MOI.modify(backend(structure.model), ci,
               DecisionCoefficientChange(index, convert(T, value)))
    return nothing
end
function JuMP.set_normalized_coefficient(structure::DeterministicEquivalent{N},
                                         ci::CI{F,S},
                                         index::VI,
                                         var_stage::Integer,
                                         stage::Integer,
                                         scenario_index::Integer,
                                         value) where {N, T, F <: Union{AffineDecisionFunction{T}, QuadraticDecisionFunction{T}}, S}
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    mapped_vi = if var_stage == 1
        mapped_vi = index
    else
        mapped_vi = mapped_index(structure, index, scenario_index)
    end
    mapped_ci = mapped_index(structure, ci, scenario_index)
    MOI.modify(backend(structure.model), mapped_ci,
               DecisionCoefficientChange(mapped_vi, convert(T, value)))
    return nothing
end

function JuMP.normalized_coefficient(structure::DeterministicEquivalent{N},
                                     ci::CI{F,S},
                                     index::VI,
                                     var_stage::Integer,
                                     stage::Integer,
                                     scenario_index::Integer) where {N, T, F <: Union{AffineDecisionFunction{T}, QuadraticDecisionFunction{T}}, S}
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    mapped_ci = mapped_index(structure, ci, scenario_index)
    f = MOI.get(structure, MOI.ConstraintFunction(), mapped_ci)::F
    dref = if var_stage == 1
        dref = DecisionRef(structure.model, index)
    else
        mapped_vi = mapped_index(structure, index, scenario_index)
        dref = DecisionRef(structure.model, mapped_vi)
    end
    return JuMP._affine_coefficient(jump_function(structure.model, f), dref)
end

function JuMP.set_normalized_rhs(structure::DeterministicEquivalent,
                                 ci::CI{F,S},
                                 value) where {T,
                                               F <: Union{AffineDecisionFunction{T}, QuadraticDecisionFunction{T}},
                                               S <: MOIU.ScalarLinearSet{T}}
    MOI.set(backend(structure.model), MOI.ConstraintSet(), ci,
            S(convert(T, value)))
    return nothing
end
function JuMP.set_normalized_rhs(structure::DeterministicEquivalent{N},
                                 ci::CI{F,S},
                                 stage::Integer,
                                 scenario_index::Integer,
                                 value) where {N,
                                               T,
                                               F <: Union{AffineDecisionFunction{T}, QuadraticDecisionFunction{T}},
                                               S <: MOIU.ScalarLinearSet{T}}
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    mapped_ci = mapped_index(structure, ci, scenario_index)
    MOI.set(backend(structure.model), MOI.ConstraintSet(), mapped_ci,
            S(convert(T, value)))
    return nothing
end

function DecisionRef(structure::DeterministicEquivalent, index::VI)
    return DecisionRef(structure.model, index)
end
function DecisionRef(structure::DeterministicEquivalent, index::VI, stage::Integer, scenario_index::Integer)
    mapped_vi = mapped_index(structure, index, scenario_index)
    return DecisionRef(structure.model, mapped_vi)
end
function DecisionRef(structure::DeterministicEquivalent{N}, index::VI, at_stage::Integer, stage::Integer, scenario_index::Integer) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    at_stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, at_stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    return DecisionRef(structure.model, index)
end

function JuMP.jump_function(structure::DeterministicEquivalent{N},
                            stage::Integer,
                            f::MOI.AbstractFunction) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    if stage == 1
        return JuMP.jump_function(structure.model, f)
    else
        return JuMP.jump_function(structure.proxy[stage], f)
    end
end
function JuMP.jump_function(structure::DeterministicEquivalent{N},
                            stage::Integer,
                            scenario_index::Integer,
                            f::MOI.AbstractFunction) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    return JuMP.jump_function(structure.model, f)
end

function JuMP.relax_integrality(structure::DeterministicEquivalent)
    unrelax = relax_decision_integrality(structure.model)
    return unrelax
end

# Getters #
# ========================== #
function structure_name(structure::DeterministicEquivalent)
    return "Deterministic equivalent"
end
function scenario_types(structure::DeterministicEquivalent{N}) where N
    return ntuple(Val{N-1}()) do i
        eltype(structure.scenarios[i])
    end
end
function proxy(structure::DeterministicEquivalent{N}, stage::Integer) where N
    1 <= stage <= N || error("Stage $stage not in range 1 to $N.")
    return structure.proxy[stage]
end
function decision(structure::DeterministicEquivalent{N}, index::MOI.VariableIndex, stage::Integer) where N
    stage == 1 || error("No scenario index specified.")
    return decision(structure.decisions, stage, index)
end
function decision(structure::DeterministicEquivalent{N}, index::MOI.VariableIndex, stage::Integer, scenario_index::Integer) where N
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    mapped_vi = mapped_index(structure, index, scenario_index)
    return decision(structure.decisions, stage, mapped_vi)
end
function scenario(structure::DeterministicEquivalent{N}, stage::Integer, scenario_index::Integer) where N
    return structure.scenarios[stage-1][scenario_index]
end
function scenarios(structure::DeterministicEquivalent{N}, stage::Integer) where N
    return structure.scenarios[stage-1]
end
function subproblem(structure::DeterministicEquivalent, stage::Integer, scenario_index::Integer)
    error("The determinstic equivalent is not decomposed into subproblems.")
end
function subproblems(structure::DeterministicEquivalent, stage::Integer)
    error("The determinstic equivalent is not decomposed into subproblems.")
end
function num_subproblems(structure::DeterministicEquivalent, stage::Integer)
    return 0
end
function deferred(structure::DeterministicEquivalent)
    return num_variables(structure.model) == 0
end
# ========================== #

# Setters
# ========================== #
function update_known_decisions!(structure::DeterministicEquivalent)
    update_known_decisions!(structure.model)
    return nothing
end
function update_known_decisions!(structure::DeterministicEquivalent, stage::Integer, scenario_index::Integer)
    stage > 1 || error("There are no scenarios in the first stage.")
    n = num_scenarios(structure, stage)
    1 <= scenario_index <= n || error("Scenario index $scenario_index not in range 1 to $n.")
    update_known_decisions!(structure.model)
    return nothing
end

function add_scenario!(structure::DeterministicEquivalent, stage::Integer, scenario::AbstractScenario)
    push!(scenarios(structure, stage), scenario)
    return nothing
end
function add_worker_scenario!(structure::DeterministicEquivalent, stage::Integer, scenario::AbstractScenario, w::Integer)
    add_scenario!(structure, scenario, stage)
    return nothing
end
function add_scenario!(scenariogenerator::Function, structure::DeterministicEquivalent, stage::Integer)
    add_scenario!(structure, stage, scenariogenerator())
    return nothing
end
function add_worker_scenario!(scenariogenerator::Function, structure::DeterministicEquivalent, stage::Integer, w::Integer)
    add_scenario!(scenariogenerator, structure, stage)
    return nothing
end
function add_scenarios!(structure::DeterministicEquivalent, stage::Integer, _scenarios::Vector{<:AbstractScenario})
    append!(scenarios(structure, stage), _scenarios)
    return nothing
end
function add_worker_scenarios!(structure::DeterministicEquivalent, stage::Integer, scenarios::Vector{<:AbstractScenario}, w::Integer)
    add_scenarios!(structure, scenarios, stasge)
    return nothing
end
function add_scenarios!(scenariogenerator::Function, structure::DeterministicEquivalent, stage::Integer, n::Integer)
    for i = 1:n
        add_scenario!(structure, stage) do
            return scenariogenerator()
        end
    end
    return nothing
end
function add_worker_scenarios!(scenariogenerator::Function, structure::DeterministicEquivalent, stage::Integer, n::Integer, w::Integer)
    add_scenarios!(scenariogenerator, structure, n, stage)
    return nothing
end
function sample!(structure::DeterministicEquivalent, stage::Integer, sampler::AbstractSampler, n::Integer)
    sample!(scenarios(structure, stage), sampler, n)
    return nothing
end
# ========================== #

# Indices
# ========================== #
function mapped_index(structure::DeterministicEquivalent{2}, index::MOI.VariableIndex, scenario_index::Integer)
    # The initial number of first-stage decisions is always given by
    num_first_stage_decisions = MOI.get(structure.proxy[1], MOI.NumberOfConstraints{MOI.SingleVariable,SingleDecisionSet{Float64}}())
    # Calculate offset from first-stage auxilliary variables (first-stage decisions are included in second-stage proxy, so deduct them)
    first_stage_offset = MOI.get(structure.proxy[1], MOI.NumberOfVariables()) - num_first_stage_decisions
    # Calculate offset from extra counts of first-stage decisions from second-stage proxy
    first_stage_decision_offset = -(scenario_index - 1) * num_first_stage_decisions
    # Calculate offset from second-stage variables
    scenario_offset = (scenario_index - 1) * MOI.get(structure.proxy[2], MOI.NumberOfVariables())
    return MOI.VariableIndex(index.value + first_stage_offset + first_stage_decision_offset + scenario_offset)
end
function mapped_index(structure::DeterministicEquivalent{2}, ci::CI{F,S}, scenario_index::Integer) where {F,S}
    first_stage_offset = MOI.get(structure.proxy[1], MOI.NumberOfConstraints{F,S}())
    scenario_offset = (scenario_index - 1) * MOI.get(structure.proxy[2], MOI.NumberOfConstraints{F,S}())
    return CI{F,S}(ci.value + first_stage_offset + scenario_offset)
end


text:
using Expectations, Distributions
using Test, Random, Statistics, LinearAlgebra

@testset "Iterable distributions" begin include("iterable.jl") end

ext: jl


text:
function connect_or_error(conn, cr::krpc.schema.ConnectionRequest)
    SendRawProto(conn, cr)
    resp = readproto(RecvRawProto(conn), krpc.schema.ConnectionResponse())
    if resp.status == krpc.schema.ConnectionResponse_Status.MALFORMED_MESSAGE
        throw("Malfomed Initial Message, Check Version")
    elseif resp.status == krpc.schema.ConnectionResponse_Status.TIMEOUT
        throw("Timeout, check network")
    elseif resp.status == krpc.schema.ConnectionResponse_Status.WRONG_TYPE
        throw("Wrong type, yell at kRPC.jl maintainer")
    end
    return resp
end

"""
    generate_stubs(conn::KRPCConnection; save_file::Bool=false)

Generate (and `eval`) the stubs offered by the server at `conn`. If `save_file` is `true`,
then the stubs will be saved into the package's directory and will be imported
the next time the wrapper is loaded.

Note that world-age restricts the use of the generated and eval'ed stubs until after the
latest age can be accessed, either by returning to the REPL, using Base.invokelatest, or
through another call to `eval`. Keep this in mind if writing a monolithic script - a function
that calls generate_stubs won't be able to immediately access the new definitions.

For more information on world age, see the documentation at https://docs.julialang.org/en/v1/manual/methods/#Redefining-Methods-1
or the paper on the topic at https://arxiv.org/abs/2010.07516.

# Examples
```julia-repl
julia> generate_stubs(conn)
```
"""
function generate_stubs(conn; save_file=false)
    serviceInfo = GetServices(conn)
    status = kerbal(conn, GetStatus_Phantom())
    ast = generateHelpers(serviceInfo, status.status)
    eval(ast)
    if save_file
        open(joinpath(@__DIR__, "generated.jl"), "w") do io;
            println(io, MacroTools.striplines(ast))
        end
    end
end

"""
    kerbal_connect(client_name::String, host::String="localhost", port::Int64=50000, stream_port::Int64=50001)

Connect to `host` at port `port` (with stream port `stream_port`) and with the displayed name `client_name`.
Default values are set up for the default localhost configuration.

# Examples

Connect to localhost as "test" and using the default ports:
```julia-repl
julia> conn = kerbal_connect("test")
```

Connect to localhost using ports 9001/9002:
```julia-repl
julia> conn = kerbal_connect("test", "localhost", 9001, 9002)
```

Connect to a server at the IP address 192.168.1.1, and ports 9001/9002:
```julia-repl
julia> conn = kerbal_connect("test", "192.168.1.1", 9001, 9002)
```
"""
function kerbal_connect(client_name::String, host::String="localhost", port::Int64=50000, stream_port::Int64=50001)
    if lastindex(client_name) > 31
        throw(ArgumentError("client name too long"))
    end

    conn = connect(host, port)
    str_conn = connect(host, stream_port)

    resp = connect_or_error(conn, krpc.schema.ConnectionRequest(client_name=client_name,_type=krpc.schema.ConnectionRequest_Type.RPC))
    connect_or_error(str_conn, krpc.schema.ConnectionRequest(client_identifier=resp.client_identifier,_type=krpc.schema.ConnectionRequest_Type.STREAM))

    active = Channel(0)
    conn = KRPCConnection(conn, str_conn, resp.client_identifier, Nothing(), Dict{UInt8, Listener}(), active)
    conn.str_listener = @async stream_listener(conn)
    bind(active, conn.str_listener)

    if isdefined(KRPC, :Interface)
        server_version = kerbal(conn, GetStatus_Phantom()).status.version
        if Interface.version != server_version
            println("Warning: current stubs version $(Interface.version) is not equal to server's version $server_version")
            println("some functions may not work correctly (or produce an error). Run KRPC.generateStubs(conn) to generate a new (one-time) copy of the stubs.")
        end
    end

    return conn
end

"""
    kerbal_connect(f::Function, client_name::String, host::String="localhost", port::Int64=50000, stream_port::Int64=50001)

Do-notation version of `kerbal_connect`, automatically closing the connection after termination of the do block.

# Examples

Connect to localhost as "test" and using the default ports:
```julia-repl
julia> kerbal_connect("test") do conn
         println("connected!")
       end
```
"""
function kerbal_connect(f::Function, client_name::String, host::String="localhost", port::Int64=50000, stream_port::Int64=50001)
    kc = kerbal_connect(client_name, host, port, stream_port)
    try
        f(kc)
    finally
        close(kc)
    end
end

function Base.close(conn::KRPCConnection)
    try put!(conn.active, false) catch e end
    Base.close(conn.conn)
end

function handle_potential_error(result)
    if ProtoBuf.hasproperty(result, :error)
        throw(kRPC.make_error(result.error))
    end
end

function make_error(err::krpc.schema.Error)
    return "A remote RPC error occured.\nThe error occured in $(err.service).$(err.name):\n$(err.description)\n$(err.stack_trace)"
end


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

name = "CImGuiPack"
version = v"0.1.2"

# Collection of sources required to build CImGuiPack
sources = [
    GitSource("https://github.com/JuliaImGui/cimgui-pack.git",
              "ecc93265e2f0f916462a2bef427f5f6b024ad6b2")
]

# Bash recipe for building across all platforms
script = raw"""
cd $WORKSPACE/srcdir/cimgui-pack
git submodule update --init --recursive
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=${prefix} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TARGET_TOOLCHAIN} -DCMAKE_BUILD_TYPE=Release
make -j${nproc}
make install
install_license ../cimgui/LICENSE ../cimgui/imgui/LICENSE.txt ../cimplot/LICENSE ../cimplot/implot/LICENSE ../cimnodes/imnodes/LICENSE.md
"""

# These are the platforms we will build for by default, unless further
# platforms are passed in on the command line
platforms = supported_platforms(; experimental=true)

# The products that we will ensure are always built
products = [
    LibraryProduct("libcimgui", :libcimgui),
    FileProduct("share/compile_commands.json", :compile_commands)
]

# Dependencies that must be installed before this package can be built
dependencies = Dependency[
]

# Build the tarballs, and possibly a `build.jl` as well.
build_tarballs(ARGS, name, version, sources, script, platforms, products, dependencies; julia_compat="1.6")

max_stars_repo_name: sharanry/Yggdrasil

max_issues_repo_name: sharanry/Yggdrasil

max_forks_repo_name: sharanry/Yggdrasil


text:
using PyPlot, DSP
# include("eegtypes.jl")

"""
    plot_spectrogram(axes, spect::Spectrogram, channel_num::Int64,
    plot_title::String="")
Display spectrogram of a chosen channel of a Spectrogram Object
"""
function plot_spectrogram(axes, spect::Spectrogram, channel_num::Int64,
  plot_title::String="")
  p = spect.power_all[channel_num]
  t = spect.time_bins
  t_first = spect.time[Int(first(t))]
  t_last = spect.time[Int(last(t))]
  f = spect.freq_bins
  fs = spect.analog_data.fs
  img = axes[:imshow](flipdim(p,1), extent=[t_first, t_last,
  fs*first(f), fs*last(f)], aspect="auto")
  xlabel("Time (s)")
  ylabel("Frequency (Hz)")
  cb = colorbar(img, orientation="horizontal", pad=0.35, fraction=0.06)
  if plot_title == ""
    title("Ch $(spect.analog_data.channel_nums[channel_num])")
  else
    title(plot_title)
  end
end

"""
    plot_spectrogram(axes, session::Session, channel_num::Int64, plot_title::String="")
Plot the spectrogram of a chosen channel of the spectrogram of a session object.
"""
function plot_spectrogram(axes, session::Session, channel_num::Int64, plot_title::String="")
  if !isnull(session.spectrum)
    if plot_title == ""
      plot_title = "Ch $(get(session.eeg_data).channel_nums[channel_num]): $(session.name)"
    end
    plot_spectrogram(axes, get(session.spectrum), channel_num, plot_title)
  else
    error("plot_spectrogram: no spectrogram in given session")
  end
end

"""
    function plot_cropped_spectrogram(axes, session::Session, channel_num::Int64, t_start::Float64,
      t_end::Float64, f_low::Float64, f_high::Float64, t_close::Array{Float64,1}=[], t_open::Array{Float64,1}=[], legend_title::String=
      "", plot_title::String="")
Plot the spectrogram of a chosen channel of the spectrogram of a session object, cropped to the times and amplitude limits specified.
Put bar below areas of the graph where eyes are closed (or other types of time periods put into t_close and t_open).
"""
function plot_cropped_spectrogram(axes, session::Session, channel_num::Int64, t_start::Float64,
  t_end::Float64, f_low::Float64, f_high::Float64, t_close::Array{Float64,1}=[], t_open::Array{Float64,1}=[], legend_title::String=
  "", plot_title::String="")
  if !isnull(session.spectrum)
    plot_title = "Ch $(get(session.eeg_data).channel_nums[channel_num]): $(session.name)"
    spect = get(session.spectrum)
    p = spect.power_all[channel_num]
    t = spect.time_bins
    t_first = spect.time[Int(first(t))]
    t_last = spect.time[Int(last(t))]
    f = spect.freq_bins
    fs = spect.analog_data.fs
    img = axes[:imshow](flipdim(p,1), extent=[t_first, t_last,
    fs*first(f), fs*last(f)], aspect="auto")
    xlabel("Time (s)")
    ylabel("Frequency (Hz)")
    xlim(t_start,t_end)
    ylim(f_low-7, f_high)
    cb = colorbar(img, orientation="horizontal", pad=0.4, fraction=0.046, shrink=1.0)
    title(plot_title)
    if length(t_close) == length(t_open) && length(t_close) != 0
      for i = 1:length(t_close)
        PyPlot.plot([t_close[i], t_open[i]], [f_low - 5, f_low - 5], color="red", lw =  4, label=legend_title)
        if i == 1
          legend(bbox_to_anchor=(1.01, 1), loc=2, borderaxespad=0)
        end
      end
    elseif length(t_close) != length(t_open)
      error("t_close and t_open lengths differ")
    end
  else
    error("plot_cropped_spectrogram: no spectrogram in given session")
  end
end

"""
    plot_time(axes, eeg_data::AnalogData, channel_num::Int64,
    plot_title::String="")
Plot a channel of an analog data object vs time
"""
function plot_time(axes, eeg_data::AnalogData, channel_num::Int64,
  plot_title::String="")
  xall = eeg_data.x_all
  x = xall[channel_num, :]
  ti = eeg_data.t
  axes[:plot](ti,x)
  title(plot_title)
  xlabel("Time (s)")
  ylabel("Amplitude (uV)")
end

"""
    plot_time(axes, session::Session, channel_num::Int64, plot_title::String="")
Plot a channel of an analog data object of a session object vs time.
"""
function plot_time(axes, session::Session, channel_num::Int64, plot_title::String="")
  if !isnull(session.eeg_data)
    plot_time(axes, get(session.eeg_data), channel_num, plot_title)
    if plot_title==""
      plot_title = "Ch $(get(session.eeg_data).channel_nums[channel_num]): $(session.name)"
    end
  else
    error("plot_time: no eeg_data in given session")
  end
end

"""
    function plot_cropped_time(axes, session::Session, channel_num::Int64, t_start::Float64,
      t_end::Float64, a_low::Float64, a_high::Float64, t_close::Array{Float64,1}=[], t_open::Array{Float64,1}=[], legend_title::String="",
      plot_title::String="")
Plot a channel of an analog data object of a session vs time, cropped to the times and amplitude limits specified.
Shade areas of the graph where eyes are closed (or other types of time periods put into t_close and t_open).
"""
function plot_cropped_time(axes, session::Session, channel_num::Int64, t_start::Float64,
  t_end::Float64, a_low::Float64, a_high::Float64, t_close::Array{Float64,1}=[], t_open::Array{Float64,1}=[], legend_title::String="",
  plot_title::String="")
  if !isnull(session.eeg_data)
    plot_title = "Ch $(get(session.eeg_data).channel_nums[channel_num]): $(session.name)"
    plot_time(axes, get(session.eeg_data), channel_num, plot_title)
    xlim(t_start,t_end)
    ylim(a_low-7, a_high)
    if length(t_close) == length(t_open) && length(t_close) != 0
      for i = 1:length(t_close)
        axvspan(t_close[i], t_open[i], color="pink", label=legend_title)
        if i == 1
          legend(bbox_to_anchor=(1.01, 1), loc=2, borderaxespad=0)
        end
      end
    elseif length(t_close) != length(t_open)
      error("t_close and t_open lengths differ")
    end
  else
    error("plot_cropped_time: no eeg_data in given session")
  end
end


text:
module WavGen

export writeToWav

# writes sound data to WAV file
# - fname : name of output file
# - data : array of sound signal
# - samplerate : number of samples per second
function writeToWav(fname :: String, data :: Array{<:Number, 1}, samplerate :: Integer)
    out =  open(fname, "w")
    outputType = Int16
    bytenum = sizeof(outputType)
    subchunk2size = length(data) * bytenum
    chunksize = 36 + subchunk2size

    write(out, "RIFF")
    write(out, Int32(chunksize))
    write(out, "WAVE")

    write(out, "fmt ")
    write(out, Int32(16)) # PCM
    write(out, Int16(1)) # linear quantization
    write(out, Int16(1)) # mono
    write(out, Int32(samplerate))
    write(out, Int32(samplerate*bytenum))
    write(out, Int16(bytenum))
    write(out, Int16(8*bytenum))

    write(out, "data")
    write(out, Int32(subchunk2size))
    write(out, Array{Int16,1}(map(floor, data)))

    close(out)
end

end

max_stars_repo_name: agostonsipos/synthesizer

max_issues_repo_name: agostonsipos/synthesizer

max_forks_repo_name: agostonsipos/synthesizer


text:
#
# Manopt.jl – basic algorithms
#
# A collection of simple algorithms that might be helpful
#
# ---
# Manopt.jl – Ronny Bergmann – 2017-07-06
import Statistics: mean, median
export mean, median, variance
export useGradientDescent, useSubgradientDescent, useProximalPoint, useCyclicProximalPoint, useDouglasRachford
# Indicators for Algorithms
struct useGradientDescent end
struct useSubgradientDescent end
struct useProximalPoint end
struct useCyclicProximalPoint end
struct useDouglasRachford end

"""
    y = mean(M,x)

compute the Riemannian center of mass of the data given by the vector of
[`MPoint`](@ref)s `x` on the [`Manifold`](@ref) `M`.
calculates the Riemannian Center of Mass (Karcher mean) of the input data `x`
as an `Array` of [`MPoint`](@ref)s on the [`Manifold`](@ref) with a
[`steepestDescent`](@ref) or a [`cyclicProximalPoint`](@ref).

# Optional
* `initialValue` – (`x[1]`) the value to initialize the algorithm to
* `method` – (`:GradientDescent`) symbol indicating the algorithm to use,
  so the second variant is `:CyclicProximalPoint`
* `weights` – (`1/n`) compute a weighted Karcher mean, i.e. the dault is to
  set all weights to be `1/n` where `n` is the length of `x`.

as well as optional parameters that are passed down to the corresponding algorithm
"""
function mean(M::mT, x::Vector{T};
    initialValue::T = x[1],
    method::Symbol = :GradientDescent,
    weights = 1/length(x)*ones(length(x)),
    kwargs...)::T where {mT <: Manifold, T <: MPoint}
  return mean_(M,x,initialValue,weights,Val(method);kwargs...)
end
function mean_(M,x,x0,w,::Val{:GradientDescent};kwargs...)
    F = y -> sum(w .* 1/2 .* distance.(Ref(M),Ref(y),x).^2)
    ∇F = y -> sum( w.*gradDistance.(Ref(M),x,Ref(y)))
    return steepestDescent(M,F,∇F,x0; kwargs...)
end
function mean_(M,x,x0,w,::Val{:CyclicProximalPoint};kwargs...)
    F = y -> sum(w .* 1/2 .* distance.(Ref(M),Ref(y),x).^2)
    proxes = Function[ (λ,y) -> proxDistance(M, λ*wi, xi, y) for (wi,xi) in zip(w,x) ]
    return cyclicProximalPoint(M,F,proxes,x0; kwargs...)
end
@doc doc"""
    y = median(M,x)

compute the median of the data given by the vector of
[`MPoint`](@ref)s `x` on the [`Manifold`](@ref) `M`.
calculates the Riemannian Center of Mass (Karcher mean) of the input data `x`
as an `Array` of [`MPoint`](@ref)s on the [`Manifold`](@ref) with a
[`cyclicProximalPoint`](@ref).

# Optional

* `initialValue` – (`x[1]`) the value to initialize the algorithm to
* `method` – (`:CyclicProximalPoint`) symbol indicating the algorithm to use
* `weights` – (`1/n`) compute a weighted Karcher mean, i.e. the dault is to
  set all weights to be `1/n` where `n` is the length of `x`.

as well as optional parameters that are passed down to the corresponding algorithm
"""
function median(M::mT, x::Vector{T};
    initialValue::T = x[1],
    method::Symbol = :CyclicProximalPoint,
    weights = 1/length(x)*ones(length(x)),
    kwargs...)::T where {mT <: Manifold, T <: MPoint}
  return median_(M,x,initialValue,weights,Val(method);kwargs...)
end
function median_(M,x,x0,w,::Val{:CyclicProximalPoint};kwargs...)
    F = y -> sum(w .* 1/2 .* distance.(Ref(M),Ref(y),x))
    proxes = Function[ (λ,y) -> proxDistance(M, λ*wi, xi, y,1) for (wi,xi) in zip(w,x) ]
    return cyclicProximalPoint(M,F,proxes,x0; kwargs...)
end

"""
    variance(M,x)

returns the variance of the vector `x` of [`MPoint`](@ref)s on the
[`Manifold`](@ref) `M`
"""
function variance(M::mT,x::Vector{T};kwargs...) where {mT<:Manifold,T<:MPoint}
  meanX = mean(M,x;kwargs...)
  return 1/( (length(x)-1)*manifoldDimension(M) ) * sum( distance.(Ref(M),Ref(meanX),x).^2 )
end


text:
module AOM

using DataFrames, Dates, ShiftedArrays
using Statistics: mean, std
using StatsBase: tiedrank
using CSV: read
using Plots, Plots.PlotMeasures

include("constants.jl")
include("clans.jl")
include("load_results.jl")
include("elaborate.jl")
include("passage_for_sharing.jl")
include("plotting.jl")

export savefig
export past_members, curr_members
export append_stats, get_stats
export repeat_by!, delta, cust_z, ZScores, elaborate, update_results
export lastweek, adjust_to_show
export plot_results
export RequiemFusion, BoethiasChampions

end # module


text:
# This file is a part of StringEncodings.jl. License is MIT: http://julialang.org/license

module StringEncodings
using Base.Libc: errno, strerror, E2BIG, EINVAL, EILSEQ
using Compat: String, ASCIIString, UTF8String, view

import Base: close, eachline, eof, flush, isreadable, iswritable,
             open, readline, readlines, readuntil, show, write
import Compat: read

export StringEncoder, StringDecoder, encode, decode, encodings
export StringEncodingError, OutputBufferError, IConvError
export InvalidEncodingError, InvalidSequenceError, IncompleteSequenceError

include("encodings.jl")
using StringEncodings.Encodings
export encoding, encodings_list, Encoding, @enc_str

abstract StringEncodingError

# Specified encodings or the combination are not supported by iconv
type InvalidEncodingError <: StringEncodingError
    args::Tuple{ASCIIString, ASCIIString}
end
InvalidEncodingError(from, to) = InvalidEncodingError((from, to))
message(::Type{InvalidEncodingError}) = "Conversion from <<1>> to <<2>> not supported by iconv implementation, check that specified encodings are correct"

# Encountered invalid byte sequence
type InvalidSequenceError <: StringEncodingError
    args::Tuple{ASCIIString}
end
InvalidSequenceError(seq::Vector{UInt8}) = InvalidSequenceError((bytes2hex(seq),))
message(::Type{InvalidSequenceError}) = "Byte sequence 0x<<1>> is invalid in source encoding or cannot be represented in target encoding"

type IConvError <: StringEncodingError
    args::Tuple{ASCIIString, Int, ASCIIString}
end
IConvError(func::String) = IConvError((func, errno(), strerror(errno())))
message(::Type{IConvError}) = "<<1>>: <<2>> (<<3>>)"

# Input ended with incomplete byte sequence
type IncompleteSequenceError <: StringEncodingError ; end
message(::Type{IncompleteSequenceError}) = "Incomplete byte sequence at end of input"

type OutputBufferError <: StringEncodingError ; end
message(::Type{OutputBufferError}) = "Ran out of space in the output buffer"

function show(io::IO, exc::StringEncodingError)
    str = message(typeof(exc))
    for i = 1:length(exc.args)
        str = replace(str, "<<$i>>", exc.args[i])
    end
    print(io, str)
end

show{T<:Union{IncompleteSequenceError,OutputBufferError}}(io::IO, exc::T) =
    print(io, message(T))

depsjl = joinpath(dirname(@__FILE__), "..", "deps", "deps.jl")
isfile(depsjl) ? include(depsjl) : error("libiconv not properly installed. Please run\nPkg.build(\"StringEncodings\")")

## iconv wrappers

function iconv_close(cd::Ptr{Void})
    if cd != C_NULL
        ccall((:iconv_close, libiconv), Cint, (Ptr{Void},), cd) == 0 ||
            throw(IConvError("iconv_close"))
    end
end

function iconv_open(tocode::String, fromcode::String)
    p = ccall((:iconv_open, libiconv), Ptr{Void}, (Cstring, Cstring), tocode, fromcode)
    if p != Ptr{Void}(-1)
        return p
    elseif errno() == EINVAL
        throw(InvalidEncodingError(fromcode, tocode))
    else
        throw(IConvError("iconv_open"))
    end
end

## StringEncoder and StringDecoder common functions

const BUFSIZE = 100

type StringEncoder{F<:Encoding, T<:Encoding, S<:IO} <: IO
    stream::S
    closestream::Bool
    cd::Ptr{Void}
    inbuf::Vector{UInt8}
    outbuf::Vector{UInt8}
    inbufptr::Ref{Ptr{UInt8}}
    outbufptr::Ref{Ptr{UInt8}}
    inbytesleft::Ref{Csize_t}
    outbytesleft::Ref{Csize_t}
end

type StringDecoder{F<:Encoding, T<:Encoding, S<:IO} <: IO
    stream::S
    closestream::Bool
    cd::Ptr{Void}
    inbuf::Vector{UInt8}
    outbuf::Vector{UInt8}
    inbufptr::Ref{Ptr{UInt8}}
    outbufptr::Ref{Ptr{UInt8}}
    inbytesleft::Ref{Csize_t}
    outbytesleft::Ref{Csize_t}
    skip::Int
end

# This is called during GC, just make sure C memory is returned, don't throw errors
function finalize(s::Union{StringEncoder, StringDecoder})
    if s.cd != C_NULL
        iconv_close(s.cd)
        s.cd = C_NULL
        # To ensure that eof() returns true without an additional check
        if isa(s, StringDecoder)
            s.outbytesleft[] = BUFSIZE
            s.skip = 0
        end
    end
    nothing
end

function iconv!(cd::Ptr{Void}, inbuf::Vector{UInt8}, outbuf::Vector{UInt8},
                inbufptr::Ref{Ptr{UInt8}}, outbufptr::Ref{Ptr{UInt8}},
                inbytesleft::Ref{Csize_t}, outbytesleft::Ref{Csize_t})
    inbufptr[] = pointer(inbuf)
    outbufptr[] = pointer(outbuf)

    inbytesleft_orig = inbytesleft[]
    outbytesleft[] = BUFSIZE

    ret = ccall((:iconv, libiconv), Csize_t,
                (Ptr{Void}, Ptr{Ptr{UInt8}}, Ref{Csize_t}, Ptr{Ptr{UInt8}}, Ref{Csize_t}),
                cd, inbufptr, inbytesleft, outbufptr, outbytesleft)

    if ret == -1 % Csize_t
        err = errno()

        # Should never happen unless a very small buffer is used
        if err == E2BIG && outbytesleft[] == BUFSIZE
            throw(OutputBufferError())
        # Output buffer is full, or sequence is incomplete:
        # copy remaining bytes to the start of the input buffer for next time
        elseif err == E2BIG || err == EINVAL
            copy!(inbuf, 1, inbuf, inbytesleft_orig-inbytesleft[]+1, inbytesleft[])
        elseif err == EILSEQ
            seq = inbuf[(inbytesleft_orig-inbytesleft[]+1):inbytesleft_orig]
            throw(InvalidSequenceError(seq))
        else
            throw(IConvError("iconv"))
        end
    end

    BUFSIZE - outbytesleft[]
end

# Reset iconv to initial state
# Returns the number of bytes written into the output buffer, if any
function iconv_reset!(s::Union{StringEncoder, StringDecoder})
    s.cd == C_NULL && return 0

    s.outbufptr[] = pointer(s.outbuf)
    s.outbytesleft[] = BUFSIZE
    ret = ccall((:iconv, libiconv), Csize_t,
                (Ptr{Void}, Ptr{Ptr{UInt8}}, Ref{Csize_t}, Ptr{Ptr{UInt8}}, Ref{Csize_t}),
                s.cd, C_NULL, C_NULL, s.outbufptr, s.outbytesleft)

    if ret == -1 % Csize_t
        err = errno()
        if err == EINVAL
            throw(IncompleteSequenceError())
        elseif err == E2BIG
            throw(OutputBufferError())
        else
            throw(IConvError("iconv"))
        end
    end

    BUFSIZE - s.outbytesleft[]
end

## StringEncoder

"""
    StringEncoder(stream, to, from=enc"UTF-8")

Returns a new write-only I/O stream, which converts any text in the encoding `from`
written to it into text in the encoding `to` written to `stream`. Calling `close` on the
stream is necessary to complete the encoding (but does not close `stream`).

`to` and `from` can be specified either as a string or as an `Encoding` object.
"""
function StringEncoder(stream::IO, to::Encoding, from::Encoding=enc"UTF-8")
    cd = iconv_open(String(to), String(from))
    inbuf = Vector{UInt8}(BUFSIZE)
    outbuf = Vector{UInt8}(BUFSIZE)
    s = StringEncoder{typeof(from), typeof(to), typeof(stream)}(stream, false,
                      cd, inbuf, outbuf,
                      Ref{Ptr{UInt8}}(pointer(inbuf)), Ref{Ptr{UInt8}}(pointer(outbuf)),
                      Ref{Csize_t}(0), Ref{Csize_t}(BUFSIZE))
    finalizer(s, finalize)
    s
end

StringEncoder(stream::IO, to::AbstractString, from::Encoding=enc"UTF-8") =
    StringEncoder(stream, Encoding(to), from)
StringEncoder(stream::IO, to::AbstractString, from::AbstractString) =
    StringEncoder(stream, Encoding(to), Encoding(from))

function show{F, T, S}(io::IO, s::StringEncoder{F, T, S})
    from = F()
    to = T()
    print(io, "StringEncoder{$from, $to}($(s.stream))")
end

# Flush input buffer and convert it into output buffer
# Returns the number of bytes written to output buffer
function flush(s::StringEncoder)
    s.cd == C_NULL && return s

    # We need to retry several times in case output buffer is too small to convert
    # all of the input. Even so, some incomplete sequences may remain in the input
    # until more data is written, which will only trigger an error on close().
    s.outbytesleft[] = 0
    while s.outbytesleft[] < BUFSIZE
        iconv!(s.cd, s.inbuf, s.outbuf, s.inbufptr, s.outbufptr, s.inbytesleft, s.outbytesleft)
        write(s.stream, view(s.outbuf, 1:(BUFSIZE - Int(s.outbytesleft[]))))
    end

    s
end

function close(s::StringEncoder)
    flush(s)
    iconv_reset!(s)
    # Make sure C memory/resources are returned
    finalize(s)
    if s.closestream
        close(s.stream)
    end
    # flush() wasn't able to empty input buffer, which cannot happen with correct data
    s.inbytesleft[] == 0 || throw(IncompleteSequenceError())
end

function write(s::StringEncoder, x::UInt8)
    s.cd == C_NULL && throw(ArgumentError("cannot write to closed StringEncoder"))
    if s.inbytesleft[] >= length(s.inbuf)
        flush(s)
    end
    s.inbuf[s.inbytesleft[]+=1] = x
    1
end

## StringDecoder

"""
    StringDecoder(stream, from, to=enc"UTF-8")

Returns a new read-only I/O stream, which converts text in the encoding `from`
read from `stream` into text in the encoding `to`.  Calling `close` on the
stream does not close `stream`.

`to` and `from` can be specified either as a string or as an `Encoding` object.

Note that some implementations (notably the Windows one) may accept invalid sequences
in the input data without raising an error.
"""
function StringDecoder(stream::IO, from::Encoding, to::Encoding=enc"UTF-8")
    cd = iconv_open(String(to), String(from))
    inbuf = Vector{UInt8}(BUFSIZE)
    outbuf = Vector{UInt8}(BUFSIZE)
    s = StringDecoder{typeof(from), typeof(to), typeof(stream)}(stream, false,
                      cd, inbuf, outbuf,
                      Ref{Ptr{UInt8}}(pointer(inbuf)), Ref{Ptr{UInt8}}(pointer(outbuf)),
                      Ref{Csize_t}(0), Ref{Csize_t}(BUFSIZE), 0)
    finalizer(s, finalize)
    s
end

StringDecoder(stream::IO, from::AbstractString, to::Encoding=enc"UTF-8") =
    StringDecoder(stream, Encoding(from), to)
StringDecoder(stream::IO, from::AbstractString, to::AbstractString) =
    StringDecoder(stream, Encoding(from), Encoding(to))

function show{F, T, S}(io::IO, s::StringDecoder{F, T, S})
    from = F()
    to = T()
    print(io, "StringDecoder{$from, $to}($(s.stream))")
end

# Fill input buffer and convert it into output buffer
# Returns the number of bytes written to output buffer
function fill_buffer!(s::StringDecoder)
    s.cd == C_NULL && return 0

    s.skip = 0

    # Input buffer and input stream empty
    if s.inbytesleft[] == 0 && eof(s.stream)
        i = iconv_reset!(s)
        return i
    end

    s.inbytesleft[] += readbytes!(s.stream, view(s.inbuf, Int(s.inbytesleft[]+1):BUFSIZE))
    iconv!(s.cd, s.inbuf, s.outbuf, s.inbufptr, s.outbufptr, s.inbytesleft, s.outbytesleft)
end

# In order to know whether more data is available, we need to:
# 1) check whether the output buffer contains data
# 2) if not, actually try to fill it (this is the only way to find out whether input
#    data contains only state control sequences which may be converted to nothing)
# 3) if not, reset iconv to initial state, which may generate data
function eof(s::StringDecoder)
    length(s.outbuf) - s.outbytesleft[] == s.skip &&
        fill_buffer!(s) == 0 &&
        iconv_reset!(s) == 0
end

function close(s::StringDecoder)
    iconv_reset!(s)
    # Make sure C memory/resources are returned
    finalize(s)
    if s.closestream
        close(s.stream)
    end
    # iconv_reset!() wasn't able to empty input buffer, which cannot happen with correct data
    s.inbytesleft[] == 0 || throw(IncompleteSequenceError())
end

function read(s::StringDecoder, ::Type{UInt8})
    s.cd == C_NULL && throw(ArgumentError("cannot read from closed StringDecoder"))
    eof(s) ? throw(EOFError()) : s.outbuf[s.skip+=1]
end

isreadable(s::StringDecoder) = s.cd != C_NULL && isreadable(s.stream)
iswritable(s::StringDecoder) = false

isreadable(s::StringEncoder) = false
iswritable(s::StringEncoder) = s.cd != C_NULL && iswritable(s.stream)

## Convenience I/O functions
function wrap_stream(s::IO, enc::Encoding)
    if iswritable(s) && isreadable(s) # Should never happen
        throw(ArgumentError("cannot open encoded text files in read and write/append modes at the same time"))
    end
    s = iswritable(s) ? StringEncoder(s, enc) : StringDecoder(s, enc)
    s.closestream = true
    s
end

"""
    open(filename::AbstractString, enc::Encoding[, args...])

Open a text file in encoding `enc`, converting its contents to UTF-8 on the fly
using `StringDecoder` (when reading) or `StringEncoder` (when writing).
`args` is passed to `open`, so this function can be used as a replacement for all `open`
variants for working with files.

Note that calling `close` on the returned I/O stream will also close the associated file handle;
this operation is necessary to complete the encoding in write mode. Opening a file for both
reading and writing/appending is not supported.

The returned I/O stream can be passed to functions working on strings without
specifying the encoding again.
"""
open(fname::AbstractString, enc::Encoding, args...) = wrap_stream(open(fname, args...), enc)

function open(fname::AbstractString, enc::Encoding,
              rd::Bool, wr::Bool, cr::Bool, tr::Bool, ff::Bool)
    if rd && (wr || ff)
        throw(ArgumentError("cannot open encoded text files in read and write/append modes at the same time"))
    end
    wrap_stream(open(fname, rd, wr, cr, tr, ff), enc)
end

function open(fname::AbstractString, enc::Encoding, mode::AbstractString)
    if mode in ("r+", "w+", "a+")
        throw(ArgumentError("cannot open encoded text files in read and write/append modes at the same time"))
    end
    wrap_stream(open(fname, mode), enc)
end

if isdefined(Base, :readstring)
    @doc """
        readstring(stream::IO, enc::Encoding)
        readstring(filename::AbstractString, enc::Encoding)

    Methods to read text in character encoding `enc`.
    """ ->
    Base.readstring(s::IO, enc::Encoding) = readstring(StringDecoder(s, enc))
    Base.readstring(filename::AbstractString, enc::Encoding) = open(io->readstring(io, enc), filename)
else # Compatibility with Julia 0.4
    @doc """
        readall(stream::IO, enc::Encoding)
        readall(filename::AbstractString, enc::Encoding)

    Methods to read text in character encoding `enc`.
    """ ->
    Base.readall(s::IO, enc::Encoding) = readall(StringDecoder(s, enc))
    Base.readall(filename::AbstractString, enc::Encoding) = open(io->readall(io, enc), filename)
end

"""
    readline(stream::IO, enc::Encoding)
    readline(filename::AbstractString, enc::Encoding)

Methods to read text in character encoding `enc`.
"""
readline(s::IO, enc::Encoding) = readline(StringDecoder(s, enc))
readline(filename::AbstractString, enc::Encoding) = open(io->readline(io, enc), filename)

"""
    readlines(stream::IO, enc::Encoding)
    readlines(filename::AbstractString, enc::Encoding)

Methods to read text in character encoding `enc`.
"""
readlines(s::IO, enc::Encoding) = readlines(StringDecoder(s, enc))
readlines(filename::AbstractString, enc::Encoding) = open(io->readlines(io, enc), filename)

"""
    readuntil(stream::IO, enc::Encoding, delim)
    readuntil(filename::AbstractString, enc::Encoding, delim)

Methods to read text in character encoding `enc`.
"""
readuntil(s::IO, enc::Encoding, delim) = readuntil(StringDecoder(s, enc), delim)
readuntil(filename::AbstractString, enc::Encoding, delim) = open(io->readuntil(io, enc, delim), filename)

"""
    eachline(stream::IO, enc::Encoding)
    eachline(filename::AbstractString, enc::Encoding)

Methods to read text in character encoding `enc`. Decoding is performed on the fly.
"""
eachline(s::IO, enc::Encoding) = eachline(StringDecoder(s, enc))
function eachline(filename::AbstractString, enc::Encoding)
    s = open(filename, enc)
    EachLine(s, ()->close(s))
end

## Functions to encode/decode strings

"""
    decode([T,] a::Vector{UInt8}, enc)

Convert an array of bytes `a` representing text in encoding `enc` to a string of type `T`.
By default, a `String` is returned.

`enc` can be specified either as a string or as an `Encoding` object.

Note that some implementations (notably the Windows one) may accept invalid sequences
in the input data without raising an error.
"""
function decode{T<:AbstractString}(::Type{T}, a::Vector{UInt8}, enc::Encoding)
    b = IOBuffer(a)
    try
        T(read(StringDecoder(b, enc, encoding(T))))
    finally
        close(b)
    end
end

decode{T<:AbstractString}(::Type{T}, a::Vector{UInt8}, enc::AbstractString) = decode(T, a, Encoding(enc))

decode(a::Vector{UInt8}, enc::AbstractString) = decode(UTF8String, a, Encoding(enc))
decode(a::Vector{UInt8}, enc::Union{AbstractString, Encoding}) = decode(UTF8String, a, enc)

"""
    encode(s::AbstractString, enc)

Convert string `s` to an array of bytes representing text in encoding `enc`.
`enc` can be specified either as a string or as an `Encoding` object.
"""
function encode(s::AbstractString, enc::Encoding)
    b = IOBuffer()
    p = StringEncoder(b, enc, encoding(typeof(s)))
    write(p, s)
    flush(p)
    takebuf_array(b)
end

encode(s::AbstractString, enc::AbstractString) = encode(s, Encoding(enc))

function test_encoding(enc::String)
    # We assume that an encoding is supported if it's possible to convert from it to UTF-8:
    cd = ccall((:iconv_open, libiconv), Ptr{Void}, (Cstring, Cstring), enc, "UTF-8")
    if cd == Ptr{Void}(-1)
        return false
    else
        iconv_close(cd)
        return true
    end
end

"""
    encodings()

List all encodings supported by `encode`, `decode`, `StringEncoder` and `StringDecoder`
(i.e. by the current iconv implementation).

Note that encodings typically appear several times under different names.
In addition to the encodings returned by this function, the empty string (i.e. `""`)
is equivalent to the encoding of the current locale.

Some implementations may support even more encodings: this can be checked by attempting
a conversion. In theory, it is not guaranteed that all conversions between all pairs of encodings
are possible; but this is the case with all reasonable implementations.
"""
function encodings()
    filter(test_encoding, encodings_list)
end

end # module


text:
using AtomEnergyLevels
using Test, Printf

@testset "AtomEnergyLevels.jl" begin
  @testset "Differentiation matrices" begin
    x = -6:0.01:6
    d²f_ex = 2(2x.^2 .- 1).*exp.(-x.^2)
    d²f_ap = laplacian(x) * exp.(-x.^2)
    @test d²f_ex ≈ d²f_ap
  end

  @testset "Parsing electronic configuration" begin
    @test c"1s1"              == [[1.0]]
    @test c"[He] 2s1"         == [[2.0, 1.0]]
    @test c"[He] 2s2 2p4"     == [[2.0, 2.0], [4.0]]
    @test c"[Xe] 4f1 5d1 6s2" == [[2.0, 2.0, 2.0, 2.0, 2.0, 2.0], [6.0, 6.0, 6.0, 6.0], [10.0, 10.0, 1.0], [1.0]]
    @test_throws DomainError conf_enc("[Ge] 1s1")
    @test_throws DomainError conf_enc("[Rn]", maxn = 5)
    @test_throws DomainError conf_enc("[He] 2d1")
    @test_throws DomainError conf_enc("1s2", spins = 1)
    @test_throws DomainError conf_enc("[He] 1s2")
  end

  @testset "DFT functionals" begin
    rₛ = [2, 5, 10, 20, 50, 100]
    ρ = 1 ./ (4π/3 * rₛ .^ 3)

    ϵ_vwn5 = [-0.0447827886146218,  -0.0281337622897314,  -0.0185445271694030,
              -0.0115476822648961,  -0.0057034884827245,  -0.0031846468815323]
    v_vwn5 = [-0.0516038239497904,  -0.0333841710353646,  -0.0225183261458631,
              -0.0143300153523442,  -0.0072495456200668,  -0.0041038158928284]

    ϵ_chac = [-0.0434298249201931,  -0.0276172696449811,  -0.0183235042675089,
              -0.0113396589743083,  -0.0054215811399318,  -0.0029196229936562]
    v_chac = [-0.0499160959362279,  -0.0326396845509736,  -0.0222371196290851,
              -0.0141507122981238,  -0.0069772050422708,  -0.0038156875497190]

    for (i, ρᵢ) in enumerate(ρ)
      vᵢ, ϵᵢ = LDA_C_VWN(ρᵢ)
      @test ϵᵢ ≈ ϵ_vwn5[i]
      @test vᵢ ≈ v_vwn5[i]
      vᵢ, ϵᵢ = LDA_C_CHACHIYO(ρᵢ)
      @test ϵᵢ ≈ ϵ_chac[i]
      @test vᵢ ≈ v_chac[i]
    end
  end

  @testset "3D isotropic harmonic oscillator" begin
    @info "3D isotropic harmonic oscillator"
    @info "https://en.wikipedia.org/wiki/Quantum_harmonic_oscillator#Example:_3D_isotropic_harmonic_oscillator"
    @info "Hamiltonian is:  H = -1/2μ⋅Δ + 1/2⋅k⋅r²"
    @info "Eigenvalues are: E = ħω⋅(2nᵣ + l + 3/2),"
    @info "where nᵣ = 0, 1, 2...; l = 0, 1, 2..., and ω² = k/μ"
    config = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
    ψ = radial_shr_eq(r -> 1/2*r^2, conf = config).orbitals
    @info "nᵣ\tl\tϵ(calc.)\tϵ(exact)\tΔϵ"
    for (quantum_numbers, orbital) in sort(collect(ψ), by = x -> last(x).ϵᵢ)
      nᵣ, l = quantum_numbers
      ϵ_calc = orbital.ϵᵢ
      ϵ_exact = 2nᵣ + l + 3/2
      @info @sprintf("%i\t%s\t%10.8f\t%10.8f\t%+0.6e",
      nᵣ, shells[l + 1], ϵ_calc, ϵ_exact, ϵ_exact - ϵ_calc)
      @test ϵ_calc ≈ ϵ_exact atol = 1e-10
    end
  end

  @testset "Hooke's atom energy" begin
    @info "Hooke's atom"
    @info "https://en.wikipedia.org/wiki/Hooke's_atom"
    @info "An exact solution for Hooke's atom is E = 2.0 a.u."
    @info "For the Xα method α is adjustable parameter."
    @info "Here we reproduce exact Hooke atom energy with α = 0.83685294"
    Xα = xc_func(xc_type_lda, false, ρ -> LDA_X(ρ, α = 0.83685294), ρ -> 0)
    Etot = lda(2, conf = c"[He]", Vex = r -> 1/8 * r^2, xc = Xα).energy.total
    @test Etot ≈ 2.0 atol = 1e-7
  end

  @testset "Argon atom" begin
    @info "Argon atom"
    @info "https://www.nist.gov/pml/atomic-reference-data-electronic-structure-calculations/atomic-reference-data-electronic-7-16"
    @info "Etot = -525.946195 (NIST)"
    E, ρ, ψ = lda(18)
    @info "Energy levels for the Ar atom are:"
    for (quantum_numbers, orbital) in sort(collect(ψ), by = x -> last(x).ϵᵢ)
      nᵣ, l = quantum_numbers
      nᵢ, ϵᵢ = orbital.nᵢ, orbital.ϵᵢ
      n = nᵣ + l + 1
      @info @sprintf("\t%i%s\t(%4.1f)\t%14.6f", n, shells[l + 1], nᵢ, ϵᵢ)
    end
    @test E.total     ≈  -525.946195 atol = 5e-7 # Etot
    @test E.kinetic   ≈   524.969812 atol = 1e-6 # Ekin
    @test E.hartree   ≈   231.458124 atol = 1e-6 # Ecoul
    @test E.potential ≈ -1253.131982 atol = 1e-6 # Eenuc
    @test E.xc        ≈   -29.242149 atol = 1e-6 # Exc

    @test ψ[(nᵣ=0, l=0)].ϵᵢ ≈  -113.800134 atol = 1e-6 # 1s
    @test ψ[(nᵣ=1, l=0)].ϵᵢ ≈   -10.794172 atol = 1e-6 # 2s
    @test ψ[(nᵣ=0, l=1)].ϵᵢ ≈    -8.443439 atol = 1e-6 # 2p
    @test ψ[(nᵣ=2, l=0)].ϵᵢ ≈    -0.883384 atol = 1e-6 # 3s
    @test ψ[(nᵣ=1, l=1)].ϵᵢ ≈    -0.382330 atol = 1e-6 # 3p
  end

  @testset "Ar+" begin
    @info "Ar+ [Ne] 3s2 3p5"
    @info "https://www.nist.gov/pml/atomic-reference-data-electronic-structure-calculations/atomic-reference-data-electronic-7-16"
    @info "Etot = -525.351708  (NIST)"
    E, ρ, ψ = lda(18, conf = c"[Ne] 3s2 3p5")
    @info "Energy levels for Ar+ are:"
    for (quantum_numbers, orbital) in sort(collect(ψ), by = x -> last(x).ϵᵢ)
      nᵣ, l = quantum_numbers
      nᵢ, ϵᵢ = orbital.nᵢ, orbital.ϵᵢ
      n = nᵣ + l + 1
      @info @sprintf("\t%i%s\t(%4.1f)\t%14.6f", n, shells[l + 1], nᵢ, ϵᵢ)
    end
    @test E.total     ≈  -525.351708 atol = 5e-7 # Etot
    @test E.kinetic   ≈   524.405209 atol = 1e-6 # Ekin
    @test E.hartree   ≈   222.915201 atol = 1e-6 # Ecoul
    @test E.potential ≈ -1243.839462 atol = 1e-6 # Eenuc
    @test E.xc        ≈   -28.832655 atol = 1e-6 # Exc

    @test ψ[(nᵣ=0, l=0)].ϵᵢ ≈  -114.320786 atol = 1e-6 # 1s
    @test ψ[(nᵣ=1, l=0)].ϵᵢ ≈   -11.303467 atol = 1e-6 # 2s
    @test ψ[(nᵣ=0, l=1)].ϵᵢ ≈    -8.954227 atol = 1e-6 # 2p
    @test ψ[(nᵣ=2, l=0)].ϵᵢ ≈    -1.337427 atol = 1e-6 # 3s
    @test ψ[(nᵣ=1, l=1)].ϵᵢ ≈    -0.816635 atol = 1e-6 # 3p
  end
end


text:
"""
    isdegenerate(N::AbstractEcologicalNetwork)

Networks are called degenerate if some species have no interactions, either at
all, or with any species other than themselves. This is particularly useful to
decide the networks to keep when generating samples for null models.
"""
function isdegenerate(N::AbstractEcologicalNetwork)
    return minimum(values(degree(nodiagonal(N)))) == 0.0
end

"""
    simplify(N::T) where {T<:AbstractEcoloigcalNetwork}

Returns a new network in which species with no interactions have been removed.
"""
function simplify(N::T) where {T<:AbstractEcologicalNetwork}
    Y = copy(N)
    simplify!(Y)
    return Y
end

"""
    simplify!{T<:BipartiteNetwork}(N::T)

Returns a new network in which species with no interactions have been removed.
"""
function simplify!(N::T) where {T<:BipartiteNetwork}
    isdegenerate(N) || return nothing
    int = interactions(N)
    from = [i.from for i in int]
    to = [i.to for i in int]
    N.T = unique(from)
    N.B = unique(to)
    I = indexin(from, N.T)
    J = indexin(to, N.B)
    N.edges = sparse(I, J, true, length(N.T), length(N.B))
    return nothing
end

"""
    simplify!{T<:BipartiteNetwork}(N::T)

Returns a new network in which species with no interactions have been removed.
"""
function simplify!(N::T) where {T<:BipartiteProbabilisticNetwork}
    isdegenerate(N) || return nothing
    int = interactions(N)
    from = [i.from for i in int]
    to = [i.to for i in int]
    N.T = unique(from)
    N.B = unique(to)
    I = indexin(from, N.T)
    J = indexin(to, N.B)
    N.edges = sparse(I, J, [i.probability for i in int], length(N.T), length(N.B))
    return nothing
end

"""
    simplify!{T<:BipartiteNetwork}(N::T)

Returns a new network in which species with no interactions have been removed.
"""
function simplify!(N::T) where {T<:BipartiteQuantitativeNetwork}
    isdegenerate(N) || return nothing
    int = interactions(N)
    from = [i.from for i in int]
    to = [i.to for i in int]
    N.T = unique(from)
    N.B = unique(to)
    I = indexin(from, N.T)
    J = indexin(to, N.B)
    N.edges = sparse(I, J, [i.strength for i in int], length(N.T), length(N.B))
    return nothing
end

"""
    simplify!(N::UnipartiteNetwork)

Modifies the network to drop all species without an interaction.
"""
function simplify!(N::T) where {T <: UnipartiteNetwork}
    isdegenerate(N) || return nothing
    int = interactions(N)
    from = [i.from for i in int]
    to = [i.to for i in int]
    sp = unique(vcat(from, to))
    I = indexin(from, sp)
    J = indexin(to, sp)
    V = true
    N.S = sp
    N.edges = sparse(I, J, V, length(sp), length(sp))
    return nothing
end

"""
    simplify!(N::UnipartiteNetwork)

Modifies the network to drop all species without an interaction.
"""
function simplify!(N::T) where {T <: UnipartiteProbabilisticNetwork}
    isdegenerate(N) || return nothing
    int = interactions(N)
    from = [i.from for i in int]
    to = [i.to for i in int]
    sp = unique(vcat(from, to))
    I = indexin(from, sp)
    J = indexin(to, sp)
    V = [i.probability for i in int]
    N.S = sp
    N.edges = sparse(I, J, V, length(sp), length(sp))
    return nothing
end

"""
    simplify!(N::UnipartiteNetwork)

Modifies the network to drop all species without an interaction.
"""
function simplify!(N::T) where {T <: UnipartiteQuantitativeNetwork}
    isdegenerate(N) || return nothing
    int = interactions(N)
    from = [i.from for i in int]
    to = [i.to for i in int]
    sp = unique(vcat(from, to))
    I = indexin(from, sp)
    J = indexin(to, sp)
    V = [i.strength for i in int]
    N.S = sp
    N.edges = sparse(I, J, V, length(sp), length(sp))
    return nothing
end


text:
# Example - BVAR
using Plots, CSV
include(joinpath(Pkg.dir("VectorAutoregressions"),"src","bvar.jl"))
plotly()

y = CSV.read(joinpath(Pkg.dir("VectorAutoregressions"),"test","bvar_data.csv"), header = false)
y = convert(Array,y[:,1:3])
const λ = 0.1:0.1:1
const τ = 10*(0.1:0.1:1)
const ε = 0.0001
const p = 4
const H = 10
const reps = 1000
const burnin = 100
const max_try = 100
const update = 100
prior = Hyperparameter(λ,τ,ε,p,H,reps,burnin,max_try,update)

mForecast = fit_bvar(y,prior)
plot(layout = grid(1,3))
for j in 1:3
plot(1:size(y,1), y[:,j])
plot!(size(y,1)+1:size(y,1)+H, [[percentile(mForecast[:,i,j],16) for i in 1:H] median(mForecast[:,:,j],1)'  [percentile(mForecast[:,i,j],84) for i in 1:H]])
end


text:
module data_loader
using CSV, DataFrames, Random

function read_csv(file_name)
    df = CSV.read("data_proj_414.csv";
    delim=",",
    types=Dict("Potter"=>Bool,
    "Weasley"=>Bool,
    "Granger"=>Bool))
    df = DataFrame(df)
    return df
end

function data_split(df, proportion=0.9)
    n = nrow(df)
    idx = shuffle(1:n)
    train_idx = view(idx, 1:floor(Int, proportion*n))
    test_idx = view(idx, (floor(Int, proportion*n)+1):n)
    train_df = df[train_idx, :]
    test_df = df[test_idx, :]
    return train_df, test_df
end

function save_csv(df, file_name)
    CSV.write(file_name, df, delim="\t")
end
end  # data_loader


text:
using Distributions
using DistributionsAD
using ForwardDiff
using Gen
struct DistributionsForwardBacked{T} <: Gen.Distribution{T}
    to_dist
    has_arg_grads :: Vector{Bool}
    has_out_grad :: Bool
end

Gen.random(d::DistributionsForwardBacked, args...) = rand(d.to_dist(args...))
Gen.logpdf(d::DistributionsForwardBacked{T}, v::T, args...) where T  = Distributions.logpdf(d.to_dist(args...), v)
Gen.logpdf_grad(d::DistributionsForwardBacked{T}, v::T,
            args...) where T = ForwardDiff.gradient((v, args...) -> Distributions.logpdf(d.to_dist(args...), v), v, args...)
(d::DistributionsForwardBacked)(args...) = Gen.random(d, args...)
Gen.has_output_grad(d::DistributionsForwardBacked) = d.has_out_grad
Gen.has_argument_grads(d::DistributionsForwardBacked) = d.has_arg_grads

max_stars_repo_name: jamesonquinn/Gen

max_issues_repo_name: jamesonquinn/Gen

max_forks_repo_name: jamesonquinn/Gen


text:
@testset "63.unique-paths-ii.jl" begin
    @test unique_path_with_obstacles_63([[0, 0, 0], [0, 1, 0], [0, 0, 0]]) == 2
    @test unique_path_with_obstacles_63([[0, 1], [0, 0]]) == 1
    @test unique_path_with_obstacles_63([
        [0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]
    ]) == 0
    @test unique_path_with_obstacles_63([[0]]) == 1
end


text:
using PrettyPlots

#gr()
#pgfplots()
a=2;
#pyplot(guidefont=font(a*17),tickfont=font(a*15),legendfont=font(a*12),titlefont=font(a*20))
#a=0.25;
#default(guidefont=font(a*17),tickfont=font(a*15),legendfont=font(a*12),titlefont=font(a*20))
plotSettings(;(:simulate=>true),(:mpc_markers =>(:circle,:blueviolet,0.0,0.0)),(:plant=>true),(:plantOnly=>false),(:size=>(a*900,a*600)),(:format=>"png"));

description=string(
"In this test: \n",c.m.name,"\n
* m.Nck=",c.m.Nck,"\n
* m.tp=",c.m.tp," \n
* m.tex=",c.m.tex,"\n
* m.max_cpu_time=",c.m.max_cpu_time," \n
* m.Nck=",c.m.Nck,"\n
* X0=",c.o.X0,"\n
* Y0=",c.o.Y0,"\n
* A=",c.o.A,"\n
* B=",c.o.B,"\n
* sx=",c.o.s_x,"\n
* sy=",c.o.s_y,"\n
")

results_dir=string("gazebo_zero_1",c.m.name,"/")
resultsDir!(n;results_name=results_dir,description=description);
savePlantData!(n)
if _pretty_defaults[:simulate];
  println("Plotting the Final Results!")
  mainSim(n,c;(:mode=>:open1))
end

optPlot(n)
posterP(n,c)

#plot(rand(10),xaxis=("test",(:guidefont=>20)))


text:
# Julia wrapper for header: /usr/local/include/libavfilter/avfilter.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0

export
    #avfilter_version,
    avfilter_configuration,
    avfilter_license,
    avfilter_copy_buffer_ref_props,
    avfilter_ref_buffer,
    avfilter_unref_buffer,
    avfilter_unref_bufferp,
    avfilter_pad_count,
    avfilter_pad_get_name,
    avfilter_pad_get_type,
    avfilter_link,
    avfilter_config_links,
    avfilter_get_video_buffer_ref_from_arrays,
    avfilter_get_audio_buffer_ref_from_arrays,
    avfilter_register_all,
    avfilter_uninit,
    avfilter_register,
    avfilter_get_by_name,
    avfilter_next,
    av_filter_next,
    avfilter_open,
    avfilter_init_filter,
    avfilter_init_str,
    avfilter_init_dict,
    avfilter_free,
    avfilter_insert_filter,
    avfilter_copy_frame_props,
    avfilter_copy_buf_props,
    avfilter_get_class,
    avfilter_graph_alloc,
    avfilter_graph_alloc_filter,
    avfilter_graph_get_filter,
    avfilter_graph_add_filter,
    avfilter_graph_create_filter,
    avfilter_graph_config,
    avfilter_graph_free,
    avfilter_inout_alloc,
    avfilter_inout_free,
    avfilter_graph_parse,
    avfilter_graph_parse2

function avfilter_version()
    ccall((:avfilter_version,libavfilter),UInt32,())
end

function avfilter_configuration()
    ccall((:avfilter_configuration,libavfilter),Ptr{UInt8},())
end

function avfilter_license()
    ccall((:avfilter_license,libavfilter),Ptr{UInt8},())
end

function avfilter_copy_buffer_ref_props(dst,src)
    ccall((:avfilter_copy_buffer_ref_props,libavfilter),Void,(Ptr{AVFilterBufferRef},Ptr{AVFilterBufferRef}),dst,src)
end

function avfilter_ref_buffer(ref,pmask::Integer)
    ccall((:avfilter_ref_buffer,libavfilter),Ptr{AVFilterBufferRef},(Ptr{AVFilterBufferRef},Cint),ref,pmask)
end

function avfilter_unref_buffer(ref)
    ccall((:avfilter_unref_buffer,libavfilter),Void,(Ptr{AVFilterBufferRef},),ref)
end

function avfilter_unref_bufferp(ref)
    ccall((:avfilter_unref_bufferp,libavfilter),Void,(Ptr{Ptr{AVFilterBufferRef}},),ref)
end

function avfilter_pad_count(pads)
    ccall((:avfilter_pad_count,libavfilter),Cint,(Ptr{AVFilterPad},),pads)
end

function avfilter_pad_get_name(pads,pad_idx::Integer)
    ccall((:avfilter_pad_get_name,libavfilter),Ptr{UInt8},(Ptr{AVFilterPad},Cint),pads,pad_idx)
end

function avfilter_pad_get_type(pads,pad_idx::Integer)
    ccall((:avfilter_pad_get_type,libavfilter),Cint,(Ptr{AVFilterPad},Cint),pads,pad_idx)
end

function avfilter_link(src,srcpad::Integer,dst,dstpad::Integer)
    ccall((:avfilter_link,libavfilter),Cint,(Ptr{AVFilterContext},UInt32,Ptr{AVFilterContext},UInt32),src,srcpad,dst,dstpad)
end

function avfilter_config_links(filter)
    ccall((:avfilter_config_links,libavfilter),Cint,(Ptr{AVFilterContext},),filter)
end

function avfilter_get_video_buffer_ref_from_arrays(data,linesize,perms::Integer,w::Integer,h::Integer,format::AVPixelFormat)
    ccall((:avfilter_get_video_buffer_ref_from_arrays,libavfilter),Ptr{AVFilterBufferRef},(Ptr{Ptr{UInt8}},Ptr{Cint},Cint,Cint,Cint,AVPixelFormat),data,linesize,perms,w,h,format)
end

function avfilter_get_audio_buffer_ref_from_arrays(data,linesize::Integer,perms::Integer,nb_samples::Integer,sample_fmt::AVSampleFormat,channel_layout::UInt64)
    ccall((:avfilter_get_audio_buffer_ref_from_arrays,libavfilter),Ptr{AVFilterBufferRef},(Ptr{Ptr{UInt8}},Cint,Cint,Cint,AVSampleFormat,UInt64),data,linesize,perms,nb_samples,sample_fmt,channel_layout)
end

function avfilter_register_all()
    ccall((:avfilter_register_all,libavfilter),Void,())
end

function avfilter_uninit()
    ccall((:avfilter_uninit,libavfilter),Void,())
end

function avfilter_register(filter)
    ccall((:avfilter_register,libavfilter),Cint,(Ptr{AVFilter},),filter)
end

function avfilter_get_by_name(name)
    ccall((:avfilter_get_by_name,libavfilter),Ptr{AVFilter},(Ptr{UInt8},),name)
end

function avfilter_next(prev)
    ccall((:avfilter_next,libavfilter),Ptr{AVFilter},(Ptr{AVFilter},),prev)
end

function av_filter_next(filter)
    ccall((:av_filter_next,libavfilter),Ptr{Ptr{AVFilter}},(Ptr{Ptr{AVFilter}},),filter)
end

function avfilter_open(filter_ctx,filter,inst_name)
    ccall((:avfilter_open,libavfilter),Cint,(Ptr{Ptr{AVFilterContext}},Ptr{AVFilter},Ptr{UInt8}),filter_ctx,filter,inst_name)
end

function avfilter_init_filter(filter,args,opaque)
    ccall((:avfilter_init_filter,libavfilter),Cint,(Ptr{AVFilterContext},Ptr{UInt8},Ptr{Void}),filter,args,opaque)
end

function avfilter_init_str(ctx,args)
    ccall((:avfilter_init_str,libavfilter),Cint,(Ptr{AVFilterContext},Ptr{UInt8}),ctx,args)
end

function avfilter_init_dict(ctx,options)
    ccall((:avfilter_init_dict,libavfilter),Cint,(Ptr{AVFilterContext},Ptr{Ptr{AVDictionary}}),ctx,options)
end

function avfilter_free(filter)
    ccall((:avfilter_free,libavfilter),Void,(Ptr{AVFilterContext},),filter)
end

function avfilter_insert_filter(link,filt,filt_srcpad_idx::Integer,filt_dstpad_idx::Integer)
    ccall((:avfilter_insert_filter,libavfilter),Cint,(Ptr{AVFilterLink},Ptr{AVFilterContext},UInt32,UInt32),link,filt,filt_srcpad_idx,filt_dstpad_idx)
end

function avfilter_copy_frame_props(dst,src)
    ccall((:avfilter_copy_frame_props,libavfilter),Cint,(Ptr{AVFilterBufferRef},Ptr{AVFrame}),dst,src)
end

function avfilter_copy_buf_props(dst,src)
    ccall((:avfilter_copy_buf_props,libavfilter),Cint,(Ptr{AVFrame},Ptr{AVFilterBufferRef}),dst,src)
end

function avfilter_get_class()
    ccall((:avfilter_get_class,libavfilter),Ptr{AVClass},())
end

function avfilter_graph_alloc()
    ccall((:avfilter_graph_alloc,libavfilter),Ptr{AVFilterGraph},())
end

function avfilter_graph_alloc_filter(graph,filter,name)
    ccall((:avfilter_graph_alloc_filter,libavfilter),Ptr{AVFilterContext},(Ptr{AVFilterGraph},Ptr{AVFilter},Ptr{UInt8}),graph,filter,name)
end

function avfilter_graph_get_filter(graph,name)
    ccall((:avfilter_graph_get_filter,libavfilter),Ptr{AVFilterContext},(Ptr{AVFilterGraph},Ptr{UInt8}),graph,name)
end

function avfilter_graph_add_filter(graphctx,filter)
    ccall((:avfilter_graph_add_filter,libavfilter),Cint,(Ptr{AVFilterGraph},Ptr{AVFilterContext}),graphctx,filter)
end

function avfilter_graph_create_filter(filt_ctx,filt,name,args,opaque,graph_ctx)
    ccall((:avfilter_graph_create_filter,libavfilter),Cint,(Ptr{Ptr{AVFilterContext}},Ptr{AVFilter},Ptr{UInt8},Ptr{UInt8},Ptr{Void},Ptr{AVFilterGraph}),filt_ctx,filt,name,args,opaque,graph_ctx)
end

function avfilter_graph_config(graphctx,log_ctx)
    ccall((:avfilter_graph_config,libavfilter),Cint,(Ptr{AVFilterGraph},Ptr{Void}),graphctx,log_ctx)
end

function avfilter_graph_free(graph)
    ccall((:avfilter_graph_free,libavfilter),Void,(Ptr{Ptr{AVFilterGraph}},),graph)
end

function avfilter_inout_alloc()
    ccall((:avfilter_inout_alloc,libavfilter),Ptr{AVFilterInOut},())
end

function avfilter_inout_free(inout)
    ccall((:avfilter_inout_free,libavfilter),Void,(Ptr{Ptr{AVFilterInOut}},),inout)
end

function avfilter_graph_parse(graph,filters,inputs,outputs,log_ctx)
    ccall((:avfilter_graph_parse,libavfilter),Cint,(Ptr{AVFilterGraph},Ptr{UInt8},Ptr{AVFilterInOut},Ptr{AVFilterInOut},Ptr{Void}),graph,filters,inputs,outputs,log_ctx)
end

function avfilter_graph_parse2(graph,filters,inputs,outputs)
    ccall((:avfilter_graph_parse2,libavfilter),Cint,(Ptr{AVFilterGraph},Ptr{UInt8},Ptr{Ptr{AVFilterInOut}},Ptr{Ptr{AVFilterInOut}}),graph,filters,inputs,outputs)
end

max_stars_repo_name: asafasban/AAVideoIO

max_issues_repo_name: asafasban/AAVideoIO

max_forks_repo_name: asafasban/AAVideoIO


text:
#!/usr/bin/env julia
#
s1 = "The quick brown fox jumps over the lazy dog α,β,γ"
println(VERSION)
# find the first instance in the string of a given character.
i = findfirst(isequal('b'), s1)
println(i)
#> 11

# or a range if called with another string
r = findfirst("brown", s1)
println(r)
#> 11:15

# replace one substring with another.
r = replace(s1, "brown" => "red")
show(r); println()
#> "The quick red fox jumps over the lazy dog"

# findfirst can also take a regular expressions by preceding the string with 'r'.
r = findfirst(r"b[\w]*n", s1)
println(r)
#> 11:15

# again with a regular expression
r = replace(s1, r"b[\w]*n" => "red")
show(r); println()
#> "The quick red fox jumps over the lazy dog"

# there are also functions for regular expressions that return RegexMatch types
r = match(r"b[\w]*n", s1)
println(r)
#> RegexMatch("brown")

# RegexMatch types have a property match that holds the matched string
show(r.match); println()
#> "brown"

# r = matchall(r"[\w]{4,}", s1)
#> SubString{UTF8String}["quick","brown","jumps","over","lazy"]
r = collect(eachmatch(r"[\w]{4,}", s1))
println(r)
#> RegexMatch[RegexMatch("quick"), RegexMatch("brown"), RegexMatch("jumps"), RegexMatch("over"), RegexMatch("lazy")]

r = eachmatch(r"[\w]{4,}", s1)
for i in r print("\"$(i.match)\" ") end
println()
#> "quick" "brown" "jumps" "over" "lazy"

r = "hello "^3
show(r); println() #> "hello hello hello "

# e.g., with one argument it strips the outer whitespace
r = strip("hello ")
show(r); println() #> "hello"
# or with a second argument of an array of chars it strips any of them;
r = strip("hello ", ['h', ' '])
show(r); println() #> "ello"
# (note the array is of chars and not strings)

r = split("hello, there,bob", ',')
show(r); println() #> ["hello"," there","bob"]
r = split("hello, there,bob", ", ")
show(r); println() #> ["hello","there,bob"]
r = split("hello, there,bob", [',', ' '], limit=0, keepempty=false)
show(r); println() #> ["hello","there","bob"]

r = join(collect(1:10), ", ")
println(r) #> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

max_stars_repo_name: wbeebe/julia

max_issues_repo_name: wbeebe/julia

max_forks_repo_name: wbeebe/julia