text:
@with_kw struct Pars
    # Economic Parameters
    θ = 2
    α = 0.33
    α_tilde = (θ - 1) / θ * α
    δ = 1.0
    γ = 1 # adjustment cost parameter

    # Shocks
    a_t = 0
    σ²ₐ = 1
    a_n = 5  # Number of nodes for productivity

    # Partial Equilibrium
    Y = 1
    R = 1.04

    # Linearly spaced grid
    K_min = 0.01
    K_max = 15
    K_n = 20 # Number of nodes for capital
    K_grid = collect(range(K_min, K_max, length=K_n))
end

@with_kw struct BPars
    τ
    w_a # Bayesian weight on the private signal
    w_p # Bayesian weight on the prior
    σ²  # Posterior uncertainty
end

"""
    Parameter set for the replication of 'Firm Learning and Growth' (2018, RED)
"""
@with_kw struct ParsGrowth
    #! Deep Parameters
    σ = 2.0   # Elasticity of Substitution
    δ = 0.1   # Probability of a firm dying
    f = 0.1   # Fixed Cost of Operating
    β = 0.96  # discount rate
    J = 1.0    # Mass of entering firms
    ξ = 13.09 # Curvature exp(z) prod shock

    z_min = 1.0    # z_min is not really important!

    #! Shocks
    θ_bar = 0     # mean demand shock
    σ²_θ = 0.997 # variance of demand shocks
    ρ = 0.9   # persistence of persistent demand

    σ²_ϵ = 1.46    # variance of transitory demand shocks with zero mean
    ϵ_bar = -σ²_ϵ / (σ * 2) # mean transient demand shock. Chosen to get a mean-preserving change in the variance.

    σ²_η = 0.3 # Variance of the innovation in persistent demand

    #! Steady State Parameters
    P = 1         # aggregate price level
    Y = 1         # aggregate expenditure
    w = 1         # wage rate
    L = 1         # Labor supply

    #! Parameters for solving the model
    N = 20 # Number of grid points
    a_min = -8
    a_max = 8
    a_grid = range(a_min, a_max, length=N)
    a_thresholds = [(a_grid[i+1] - a_grid[i]) / 2 + a_grid[i] for i = 1:length(a_grid)-1]

    N_z = 20 # Number of grid points
    z_max = 7  # Check whether few firms become so large
    z_grid = range(z_min, z_max, length=N_z) # A grid for z, which we will not really use.

    u = 0.5 # some random value
    u_grid = (exp.(z_grid) .^ (σ - 1) .* P .^ (σ - 1) .* Y ./ (w .^ (σ - 1))) .^ (1 / (σ - 1)) # Some initial value, but will be replaced later on
    u_star = 0 # Needs to be solved for!

    #! Depreciation
    unc_max = 10
    unc_min = 0.5
    uncertainty_grid = range(unc_min, unc_max, length=N_unc)
end

@with_kw struct StSt
    M # Mass of Firms
    Y # Output
    P # Price Level
    E # Entry/Exit
end

"""
    Bayesian parameter set for the replication of 'Firm Learning and Growth' (2018, RED)
"""
@with_kw struct BParsGrowth
    n     # Number of periods
    V_n   # Posterior uncertainty after n periods
    w_an  # Weight on new signal
    w_pn  # Weight on prior
end

@with_kw struct ParsV2
    #! Deep Parameters
    σ = 2.0   # Elasticity of Substitution
    δ = 0.1   # Probability of a firm dying
    f = 0.1   # Fixed Cost of Operating
    β = 0.96  # discount rate
    J = 1.0   # Mass of entering firms
    ξ = 13.09 # Curvature exp(z) prod shock

    z_min = 1.0 # Minimum firm productivity

    #! Shocks
    #θ_bar = 0     # mean demand shock
    #σ²_θ  = 0.997 # variance of demand shocks
    ρ = 0.99  # persistence of persistent demand

    σ²_ϵ = 1.46    # variance of transitory demand shocks with zero mean
    ϵ_bar = -σ²_ϵ / (σ * 2) # mean transient demand shock. Chosen to get a mean-preserving change in the variance.

    σ²_η = 0.3 # Variance of the innovation in persistent demand

    σ²_ν = 1 # Scaling variance of the signal

    #! Steady State Parameters
    P = 1         # aggregate price level
    Y = 1         # aggregate expenditure
    w = 1         # wage rate
    L = 1         # Labor supply

    #! Parameters for solving the model
    # Prior mean
    N_μ = 20 # Number of grid points
    μ_min = -8
    μ_max = 8
    μ_grid = range(μ_min, μ_max, length=N_μ)

    # To get the cut-off points for the transition matrix
    μ_thresholds = [(μ_grid[i+1] + μ_grid[i]) / 2 for i = 1:length(μ_grid)-1]

    N_V = 20
    V_min = 0.5
    V_max = 10
    V_grid = range(V_min, V_max, length=N_V)

    N_z = 20 # Number of grid points
    z_max = 7  # Check whether few firms become so large
    z_grid = range(z_min, z_max, length=N_z) # A grid for z, which we will not really use.
    #! This is from the Learning and Firm Growth Paper.
    #! Basically, some part of firm profits is fixed and can be solved for later.
    u = 0.5 # some random value
    u_grid = (exp.(z_grid) .^ (σ - 1) .* P .^ (σ - 1) .* Y ./ (w .^ (σ - 1))) .^ (1 / (σ - 1)) # Some initial value, but will be replaced later on
    u_star = 0 # Needs to be solved for!
end

@with_kw struct Pars_Bundle
    #! Deep Parameters
    σ = 2.0  # Elasticity of Substitution
    v = 1.0   # Returns to Scale
    γ = 0.5  # Relative importance of goods
    α = 0.3  # labor share
    δ = 0.1  # intangible capital share
    τ = 0.1  # Icerberg Transportation Cost
    ϕ = 0.0   # How much capital is kept by the firm that is selling capital
    α_Y = (σ * v - σ + 1) / (σ * v)

    α_hat = (σ - 1) / σ * α
    δ_hat = (σ - 1) / σ * δ

    ϵ = 2 # elasticity of substitution between capital varieties
    ξ = 0.5 # productivity of exogenous capital

    #! Steady State Parameters
    P = 1       # aggregate price level
    Y = 0.95    # aggregate output
    w = 1       # wage rate
    L = 1       # Labor supply
    p_I_A = 1       # Price of Intangible Capital of A firms
    p_I_B = 1       # Price of Intangible Capital of B firms

    #! Solution Firm-Parameters
    l_A_ss = 0
    l_B_ss = 0
    k_I_P_A_ss = 0
    k_I_P_B_ss = 0
    k_I_b_B_ss = 0
    k_I_b_A_ss = 0
    k_I_B_ss = 0
    k_I_A_ss = 0

    # More robust to calculate it once and save it than calculating it multiple times.
    #! Cost parameters
    # Multiplicative Parameter
    ca_A = 0.1
    ca_B = 0.3

    # Curvature parameter
    cb_A = 2
    cb_B = 2

end
@with_kw struct Pars_Simple
    #! Deep Parameters
    σ = 2.0  # Elasticity of Substitution
    v = 1.0   # Returns to Scale
    γ = 0.5  # Relative importance of goods
    α = 0.3  # labor share
    δ = 0.1  # intangible capital share
    τ = 0.1  # Icerberg Transportation Cost
    ϕ = 0.0   # How much capital is kept by the firm that is selling capital
    α_C = (σ * v - σ + 1) / (σ * v)

    α_hat = (σ - 1) / σ * α
    δ_hat = (σ - 1) / σ * δ

    ϵ = 2 # elasticity of substitution between capital varieties
    ξ = 0.5 # productivity of exogenous capital

    #! Steady State Parameters
    P = 1       # aggregate price level
    C = 0.95    # aggregate output
    w = 1       # wage rate
    L = 1       # Labor supply
    p_I = 1       # Price of Intangible Capital

    #! Solution Firm-Parameters
    l_A_ss = 0
    l_B_ss = 0
    k_I_P_A_ss = 0
    k_I_P_B_ss = 0
    k_I_b_B_ss = 0
    k_I_b_A_ss = 0
    k_I_B_ss = 0
    k_I_A_ss = 0

    # More robust to calculate it once and save it than calculating it multiple times.
    #! Cost parameters
    # Multiplicative Parameter
    ca_A = 0.1
    ca_B = 0.3

    # Curvature parameter
    cb_A = 2
    cb_B = 2

end
@with_kw struct Pars_OLG
    #! Deep Parameters
    σ = 2.0  # Elasticity of Substitution
    γ = 0.5  # Share of Sophisticated Firms
    α = 0.3  # labor share
    δ = 0.1  # intangible capital share
    τ = 0.1  # Icerberg Transportation Cost
    β = 0.9 # Discount Rate
    α_Y = 1 / σ
    μ = 1.0

    α_hat = (σ - 1) / σ * α
    δ_hat = (σ - 1) / σ * δ

    f = 1.5 # fixed cost

    #! Steady State Parameters
    P = 1       # aggregate price level
    Y = 0.95    # aggregate output
    w = 1       # wage rate
    L = 1       # Labor supply
    p_I = 1     # Price of Intangible Capital

    #! Solution Firm-Parameters
    l_S_ss = 0
    l_U_ss = 0
    l_Y_ss = 0
    k_P_S_ss = 0
    k_P_U_ss = 0
    k_T_U_ss = 0
    k_T_S_ss = 0
    k_T_Y_ss = 0
    k_U_ss = 0
    k_S_ss = 0
    k_Y_ss = 0

    # More robust to calculate it once and save it than calculating it multiple times.
    #! Cost parameters
    # cost = a * k ^ b
    # Multiplicative Parameter
    ca_S = 0.3
    ca_U = 5

    # Curvature parameter
    cb_S = 2
    cb_U = 2
end
"""
    The parameters and steady state values for the model written down by Ilja and Roxana.
    Main features: Firms share structured which still needs to be processed internally to generate knowledge.
    Additionally, data is partly non-rival (ν > 0). The rival-formulation is nested

"""
@with_kw struct Pars_v3
    #! Deep Parameters
    σ = 2.0  # Elasticity of Substitution
    c = ((σ - 1) / σ) # auxilary variable
    w_S = 0.5  # Share of Sophisticated Firms
    w_B = 0.5  # Share of Firms with large customer base.
    α = 0.3  # labor share, knowledge share is 1-α
    ϕ = 0.3  # diminishing returns data generation
    τ = 0.1  # icerberg transportation cost
    τ2 = 0.1  # icerberg transportation cost
    ν = 0.05 # non-rivalry parameter
    ε = 2    # elasticity of substition data bundle
    ξ = 1.0  # relative usefulness external data
    β = 0.94 # Discount Factor
    ζ = 1.0  #! Does not work and needs to be equal to 1 at the moment!!!!

    compl_prod::Symbol = :yes

    α_Y = set_a_Y(compl_prod, σ, ζ) # auxiliary paramter

    α_L_hat = (σ - 1) / σ * (1 - α) # adjusted labor factor share
    α_K_hat = (σ - 1) / σ * α # adjusted knowledge factor share

    bundle = :yes # Switch in case I want to also implement a version without the data bundle, but making ε very large is similar

    λ = 0.1234

    #! Persistent Knowledge and Data
    δ_D = 0.1 # depreciation rate for data
    δ_K = 0.1 # depreciation rate for knowledge
    second_period = :yes

    #! Steady State Parameters
    P = 1  # aggregate price level
    #! This is the solution for the model with tau = 0, nu = 0, α_Y = 0
    Y = 2.075300672340325  # aggregate output
    w = 0.2367874818108683  # wage rate good production
    w_P = 0.04669426512765732  # wage rate data processing
    w_G = 0.06021347283561476  # wage rate data generation
    L = 1  # Labor supply for production of the intermediate good
    L_P = 1  # Labor supply for processing data
    L_G = 1  # Labor supply for generating / structuring data
    p_D = 0.11356059692613776  # Price of Structured Data
    Ω = 0.0 # data multiplier, generated minus iceberg transportation plus non-rival
    Ω_bundle = 0.0 # data multiplier, bundle relative to generated

    Y2 = 2.075300672340325  # aggregate output
    w2 = 0.2367874818108683  # wage rate good production
    w_P2 = 0.04669426512765732  # wage rate data processing
    w_G2 = 0.06021347283561476  # wage rate data generation
    L2 = 1  # Labor supply for production of the intermediate good
    L_P2 = 1  # Labor supply for processing data
    L_G2 = 1  # Labor supply for generating / structuring data
    p_D2 = 0.11356059692613776  # Price of Structured Data
    Ω2 = 0.0 # data multiplier, generated minus iceberg transportation plus non-rival
    Ω_bundle2 = 0.0 # data multiplier, bundle relative to generated

    D_G_SS = 0.0 # Total data generated
    D_S_SS = 0.0 # Total data shared

    D_G_SS2 = 0.0 # Total data generated
    D_S_SS2 = 0.0 # Total data shared

    #! Firm Specific Parameters
    A_G_common = 1.0
    A_G_unsoph = 0.2
    A_P_common = 1.0
    A_P_unsoph = 1.0

    A_G_common2 = 1.0
    A_P_common2 = 1.0

    A_G_S = A_G_unsoph * A_G_common # data generation productivity parameter, small
    A_G_B = 1.0 * A_G_common # data generation productivity parameter, big
    A_P_U = A_P_unsoph * A_P_common # data processing productivity parameter, unsophisticated
    A_P_S = 1.0 * A_P_common # data processing productivity parameter, sophisticated

    γ_S = 0.2  # labor share data processing sophisticated, data share is 1-γ
    γ_U = 0.4  # labor share data processing unsophisticated, data share is 1-γ

    Firm_sol = 0

    #! Solution Firm-Parameters
    l_LU_ss = 0 # Labor good production small customer base, unsophisticated
    l_BU_ss = 0 # Labor good production big customer base, unsophisticated
    l_LS_ss = 0 # Labor good production small customer base, sophisticated
    l_BS_ss = 0 # Labor good production big customer base, sophisticated

    l_P_LU_ss = 0 # Labor good production small customer base, unsophisticated
    l_P_BU_ss = 0 # Labor good production big customer base, unsophisticated
    l_P_LS_ss = 0 # Labor good production small customer base, sophisticated
    l_P_BS_ss = 0 # Labor good production big customer base, sophisticated

    l_G_LU_ss = 0 # Labor good production small customer base, unsophisticated
    l_G_BU_ss = 0 # Labor good production big customer base, unsophisticated
    l_G_LS_ss = 0 # Labor good production small customer base, sophisticated
    l_G_BS_ss = 0 # Labor good production big customer base, sophisticated

    D_S_LU_ss = 0 # data sharing small customer base, unsophisticated
    D_S_BU_ss = 0 # data sharing big customer base, unsophisticated
    D_S_LS_ss = 0 # data sharing small customer base, sophisticated
    D_S_BS_ss = 0 # data sharing big customer base, sophisticated

    D_G_LU_ss = 0 # data generated small customer base, unsophisticated
    D_G_BU_ss = 0 # data generated big customer base, unsophisticated
    D_G_LS_ss = 0 # data generated small customer base, sophisticated
    D_G_BS_ss = 0 # data generated big customer base, sophisticated

    D_I_LU_ss = 0 # data generated small customer base, unsophisticated
    D_I_BU_ss = 0 # data generated big customer base, unsophisticated
    D_I_LS_ss = 0 # data generated small customer base, sophisticated
    D_I_BS_ss = 0 # data generated big customer base, sophisticated

    D_E_LU_ss = 0 # data generated small customer base, unsophisticated
    D_E_BU_ss = 0 # data generated big customer base, unsophisticated
    D_E_LS_ss = 0 # data generated small customer base, sophisticated
    D_E_BS_ss = 0 # data generated big customer base, sophisticated

    D_LU_ss = 0 # data generated small customer base, unsophisticated
    D_BU_ss = 0 # data generated big customer base, unsophisticated
    D_LS_ss = 0 # data generated small customer base, sophisticated
    D_BS_ss = 0 # data generated big customer base, sophisticated

    D_last_LU = 0 # data generated small customer base, unsophisticated
    D_last_BU = 0 # data generated big customer base, unsophisticated
    D_last_LS = 0 # data generated small customer base, sophisticated
    D_last_BS = 0 # data generated big customer base, sophisticated

    K_LU_ss = 0 # knowledge employed small customer base, unsophisticated
    K_BU_ss = 0 # knowledge employed big customer base, unsophisticated
    K_LS_ss = 0 # knowledge employed small customer base, sophisticated
    K_BS_ss = 0 # knowledge employed big customer base, sophisticated

    K_last_LU = 0 # knowledge employed small customer base, unsophisticated
    K_last_BU = 0 # knowledge employed big customer base, unsophisticated
    K_last_LS = 0 # knowledge employed small customer base, sophisticated
    K_last_BS = 0 # knowledge employed big customer base, sophisticated

    prof_LU_ss = 0 # knowledge employed small customer base, unsophisticated
    prof_BU_ss = 0 # knowledge employed big customer base, unsophisticated
    prof_LS_ss = 0 # knowledge employed small customer base, sophisticated
    prof_BS_ss = 0 # knowledge employed big customer base, sophisticated
end

@with_kw struct Pars_v3_simpl
    #! Deep Parameters
    σ = 2.0  # Elasticity of Substitution
    c = (σ - 1) / σ # auxilary variable
    w_S = 0.5  # Share of Sophisticated Firms
    w_B = 0.5  # Share of Firms with large customer base.
    α = 0.3  # labor share, knowledge share is 1-α
    ϕ = 0.3  # diminishing returns data generation
    τ = 0.1  # icerberg transportation cost
    ν = 0.05 # non-rivalry parameter
    ε = 2    # elasticity of substition data bundle
    ξ = 1.0  # relative usefulness external data
    β = 0.94 # Discount Factor
    ζ = 1.0  #! Does not work and needs to be equal to 1 at the moment!!!!

    α_S = 0.8  # data share data processing sophisticated, data share is 1-γ
    α_U = 0.6  # data share data processing unsophisticated, data share is 1-γ

    compl_prod::Symbol = :yes

    α_Y = set_a_Y(compl_prod, σ, ζ) # auxiliary paramter

    α_S_L_hat = (σ - 1) / σ * (1 - α_S) # adjusted labor factor share sophisticated
    α_S_K_hat = (σ - 1) / σ * α_S # adjusted knowledge factor share sophisticated

    α_U_L_hat = (σ - 1) / σ * (1 - α_U) # adjusted labor factor share unsophisticated
    α_U_K_hat = (σ - 1) / σ * α_U # adjusted knowledge factor share unsophisticated

    bundle = :yes # Switch in case I want to also implement a version without the data bundle, but making ε very large is similar

    #! Rate of convergence
    λ = 0.1234

    #! Steady State Parameters
    P = 1  # aggregate price level
    #! This is the solution for the model with tau = 0, nu = 0, α_Y = 0
    Y = 2.075300672340325  # aggregate output
    w = 0.2367874818108683  # wage rate good production
    w_P = 0.04669426512765732  # wage rate data processing
    w_G = 0.06021347283561476  # wage rate data generation
    L = 1  # Labor supply for production of the intermediate good
    L_P = 1  # Labor supply for processing data
    L_G = 1  # Labor supply for generating / structuring data
    p_D = 0.11356059692613776  # Price of Structured Data
    Ω = 0.0 # data multiplier, generated minus iceberg transportation plus non-rival
    Ω_bundle = 0.0 # data multiplier, bundle relative to generated

    D_G_SS = 0.0 # Total data generated
    D_S_SS = 0.0 # Total data shared

    #! Firm Specific Parameters
    A_G_common = 1.0
    A_G_unsoph = 0.2
    A_P_common = 1.0
    A_P_unsoph = 1.0

    A_G_S = A_G_unsoph * A_G_common # data generation productivity parameter, small
    A_G_B = 1.0 * A_G_common # data generation productivity parameter, big
    A_P_U = A_P_unsoph * A_P_common # data processing productivity parameter, unsophisticated
    A_P_S = 1.0 * A_P_common # data processing productivity parameter, sophisticated

    Firm_sol = 0

    #! Solution Firm-Parameters
    l_LU_ss = 0 # Labor good production small customer base, unsophisticated
    l_BU_ss = 0 # Labor good production big customer base, unsophisticated
    l_LS_ss = 0 # Labor good production small customer base, sophisticated
    l_BS_ss = 0 # Labor good production big customer base, sophisticated

    l_G_LU_ss = 0 # Labor good production small customer base, unsophisticated
    l_G_BU_ss = 0 # Labor good production big customer base, unsophisticated
    l_G_LS_ss = 0 # Labor good production small customer base, sophisticated
    l_G_BS_ss = 0 # Labor good production big customer base, sophisticated

    D_S_LU_ss = 0 # data sharing small customer base, unsophisticated
    D_S_BU_ss = 0 # data sharing big customer base, unsophisticated
    D_S_LS_ss = 0 # data sharing small customer base, sophisticated
    D_S_BS_ss = 0 # data sharing big customer base, sophisticated

    D_G_LU_ss = 0 # data generated small customer base, unsophisticated
    D_G_BU_ss = 0 # data generated big customer base, unsophisticated
    D_G_LS_ss = 0 # data generated small customer base, sophisticated
    D_G_BS_ss = 0 # data generated big customer base, sophisticated

    D_I_LU_ss = 0 # data generated small customer base, unsophisticated
    D_I_BU_ss = 0 # data generated big customer base, unsophisticated
    D_I_LS_ss = 0 # data generated small customer base, sophisticated
    D_I_BS_ss = 0 # data generated big customer base, sophisticated

    D_E_LU_ss = 0 # data generated small customer base, unsophisticated
    D_E_BU_ss = 0 # data generated big customer base, unsophisticated
    D_E_LS_ss = 0 # data generated small customer base, sophisticated
    D_E_BS_ss = 0 # data generated big customer base, sophisticated

    D_LU_ss = 0 # data generated small customer base, unsophisticated
    D_BU_ss = 0 # data generated big customer base, unsophisticated
    D_LS_ss = 0 # data generated small customer base, sophisticated
    D_BS_ss = 0 # data generated big customer base, sophisticated

    K_LU_ss = 0 # knowledge employed small customer base, unsophisticated
    K_BU_ss = 0 # knowledge employed big customer base, unsophisticated
    K_LS_ss = 0 # knowledge employed small customer base, sophisticated
    K_BS_ss = 0 # knowledge employed big customer base, sophisticated

    prof_LU_ss = 0 # knowledge employed small customer base, unsophisticated
    prof_BU_ss = 0 # knowledge employed big customer base, unsophisticated
    prof_LS_ss = 0 # knowledge employed small customer base, sophisticated
    prof_BS_ss = 0 # knowledge employed big customer base, sophisticated
end

@with_kw struct Firm_sol
    #! Solution for firm parameters
    l_LU_ss = 0 # Labor good production small customer base, unsophisticated
    l_BU_ss = 0 # Labor good production big customer base, unsophisticated
    l_LS_ss = 0 # Labor good production small customer base, sophisticated
    l_BS_ss = 0 # Labor good production big customer base, sophisticated

    l_P_LU_ss = 0 # Labor good production small customer base, unsophisticated
    l_P_BU_ss = 0 # Labor good production big customer base, unsophisticated
    l_P_LS_ss = 0 # Labor good production small customer base, sophisticated
    l_P_BS_ss = 0 # Labor good production big customer base, sophisticated

    l_G_LU_ss = 0 # Labor good production small customer base, unsophisticated
    l_G_BU_ss = 0 # Labor good production big customer base, unsophisticated
    l_G_LS_ss = 0 # Labor good production small customer base, sophisticated
    l_G_BS_ss = 0 # Labor good production big customer base, sophisticated

    D_S_LU_ss = 0 # data sharing small customer base, unsophisticated
    D_S_BU_ss = 0 # data sharing big customer base, unsophisticated
    D_S_LS_ss = 0 # data sharing small customer base, sophisticated
    D_S_BS_ss = 0 # data sharing big customer base, sophisticated

    D_G_LU_ss = 0 # data generated small customer base, unsophisticated
    D_G_BU_ss = 0 # data generated big customer base, unsophisticated
    D_G_LS_ss = 0 # data generated small customer base, sophisticated
    D_G_BS_ss = 0 # data generated big customer base, sophisticated

    D_I_LU_ss = 0 # data generated small customer base, unsophisticated
    D_I_BU_ss = 0 # data generated big customer base, unsophisticated
    D_I_LS_ss = 0 # data generated small customer base, sophisticated
    D_I_BS_ss = 0 # data generated big customer base, sophisticated

    D_E_LU_ss = 0 # data generated small customer base, unsophisticated
    D_E_BU_ss = 0 # data generated big customer base, unsophisticated
    D_E_LS_ss = 0 # data generated small customer base, sophisticated
    D_E_BS_ss = 0 # data generated big customer base, sophisticated

    D_LU_ss = 0 # data generated small customer base, unsophisticated
    D_BU_ss = 0 # data generated big customer base, unsophisticated
    D_LS_ss = 0 # data generated small customer base, sophisticated
    D_BS_ss = 0 # data generated big customer base, sophisticated

    D_last_LU = 0 # data generated small customer base, unsophisticated
    D_last_BU = 0 # data generated big customer base, unsophisticated
    D_last_LS = 0 # data generated small customer base, sophisticated
    D_last_BS = 0 # data generated big customer base, sophisticated

    K_LU_ss = 0 # knowledge employed small customer base, unsophisticated
    K_BU_ss = 0 # knowledge employed big customer base, unsophisticated
    K_LS_ss = 0 # knowledge employed small customer base, sophisticated
    K_BS_ss = 0 # knowledge employed big customer base, sophisticated

    K_last_LU = 0 # knowledge employed small customer base, unsophisticated
    K_last_BU = 0 # knowledge employed big customer base, unsophisticated
    K_last_LS = 0 # knowledge employed small customer base, sophisticated
    K_last_BS = 0 # knowledge employed big customer base, sophisticated

    prof_LU_ss = 0 # knowledge employed small customer base, unsophisticated
    prof_BU_ss = 0 # knowledge employed big customer base, unsophisticated
    prof_LS_ss = 0 # knowledge employed small customer base, sophisticated
    prof_BS_ss = 0 # knowledge employed big customer base, sophisticated
end


text:
function chain(op1, op2...)
    Expr(:call, op1, op2...)
end

function gen_op(ta::TimeArray)
    cols = ta.colnames
    box  = Any[]
    for c in cols
        push!(box, (Symbol(c), c))
    end
    for (fn, name) in box
        @eval begin
            function $fn(ta)
                ta[$name]
            end
        end
    end
end

ext: jl


text:
function fit_nfolds!(xx_train,yy_train,nof_folds,vars,i_train,i_fold,cc1,neurons)# ,inds_all,n_per_part,neurons)
    maetrs=Array{Float64}(undef,0)
    a_all_all=Vector{Vector{Vector{Float64}}}()
    a_layer1_all=Vector{Vector{Float64}}()
    n_per_part_all=Vector{Vector{Int64}}()
    inds_all_all=Vector{Vector{Int64}}()
    xx_fold_all=Vector{Array{Float64}}()
    neurons_all=Vector{Int64}()
    pred_folds_all=zeros(i_fold,nof_folds)
    for i=1:nof_folds
        inds_fold=randperm(i_train)[1:i_fold]
        # inds_fold=1:i_fold
        xx_fold=copy(xx_train[inds_fold,:]);push!(xx_fold_all,xx_fold);
        yy_fold=copy(yy_train[inds_fold])
        # neurons=Int64(floor(i_fold/(vars+1)))   # todo: change number of neurons for each fold
        # neurons=10
        # push!(neurons_all,neurons)
        inds_all_vec_unvec,n_per_part_new=___clustering(neurons,xx_fold,200)
        # inds_all=randperm(i_fold);items_per_neuron=(Int64(floor(i_fold/(neurons))))*ones(Int64,neurons)
        # n_per_part=[0;cumsum(items_per_neuron)];n_per_part[end]=i_train

		inds_fold=randperm(i_train)[1:i_fold];
        # xx_fold=copy(xx_train[inds_fold,:]);push!(xx_fold_all,xx_fold);
        # yy_fold=copy(yy_train[inds_fold])
        # neurons=Int64(floor(i_fold/(vars+1)))   # todo: change number of neurons for each fold
        # neurons=20
        push!(neurons_all,neurons);
        # inds_all,n_per_part=___clustering(neurons,xx_fold,200)

        # n_per_part_new=copy(n_per_part);
        # inds_all_vec=Vector{Vector{Int64}}();
        # k=0
        # for ii=1:length(n_per_part)-1
        #     iii=inds_all[n_per_part[ii]+1:n_per_part[ii+1]];
        #     vec1=Vector{Int64}();
        #     for j=1:length(iii)
        #         if iii[j] in inds_fold
        #             k+=1
        #             # println(k," ",iii[j])
        #             push!(vec1,k);
        #         end

        #     end
        #     n_per_part_new[ii+1]=n_per_part_new[ii]+length(vec1);
        #     push!(inds_all_vec,vec1);
        # end
        # inds_all_vec_unvec=Vector{Int64}();
        # for ii=1:length(n_per_part_new)-1
        #     inds_all_vec_unvec=[inds_all_vec_unvec;inds_all_vec[ii]];
        # end
        # xx_fold=copy(xx_train[inds_fold,:]);push!(xx_fold_all,xx_fold);
        # yy_fold=copy(yy_train[inds_fold]);

        # println("training ",i)
        # println(n_per_part_new)
        # println(inds_all_vec_unvec)
        # println(size(inds_all_vec_unvec),size(n_per_part_new),size(inds_all_vec))

        # return maetrs,a_all_all,a_layer1_all,n_per_part_all,inds_all_all,xx_fold_all,neurons_all

        a_all,a_layer1,layer1=train_layer_1_rbf(neurons,vars,i_fold,n_per_part_new,inds_all_vec_unvec,xx_fold,yy_fold,cc1)
        push!(a_all_all,a_all);push!(a_layer1_all,a_layer1);push!(n_per_part_all,n_per_part_new);push!(inds_all_all,inds_all_vec_unvec);

        # predl1=predict_new_rbf(a_all,a_layer1,xx_train,i_train,neurons,n_per_part,inds_all,xx_fold,vars,cc1)
        # # i1=predl1.<=0.5;predl1[i1].=0.1;i1=predl1.>0.5;predl1[i1].=0.9;i2=(predl1.-yy_train).<0.01;maetr=sum(i2)/length(i2);
        # maetr=mean(abs.(yy_train-predl1))
        # push!(maetrs,maetr);

        predl1=[layer1 ones(i_fold)]*a_layer1
        pred_folds_all[:,i].=predl1
        maetr=mean(abs.(yy_fold-predl1))
        # i1=predl1.<=0.5;predl1[i1].=0.1;i1=predl1.>0.5;predl1[i1].=0.9;i2=abs.(predl1.-yy_fold).<0.01;maetr=1.0-sum(i2)/length(i2)
        # if maetr<1e-4 maetr=1e-4 end
        push!(maetrs,maetr);

        println(Dates.format(now(), "HH:MM:SS"), " ",i, " maetr=",maetr)
    end
    return maetrs,a_all_all,a_layer1_all,n_per_part_all,inds_all_all,xx_fold_all,neurons_all,pred_folds_all
end


text:
immutable Entity{S,D,I} # state, definition, identification
    state::S
    def::D
    id::I
end
Entity{S,D,I}(entity::Entity{S,D,I}, s::S) = Entity(s, entity.def, entity.id)


text:
using Test

@info "CANalyze.Signals tests..."
@testset "bit_signal" begin
    using CANalyze.Signals

    @testset "bit_signal_1" begin
        signal = Bit(20)
        @test true
    end

    @testset "bit_signal_2" begin
        signal = Bit(start=20)
        @test true
    end

    @testset "start_1" begin
        signal = Bit(start=20)
        @test start(signal) == 20
    end

    @testset "byte_order_1" begin
        signal = Bit(start=20)
        @test byte_order(signal) == :little_endian
    end

    @testset "length_1" begin
        signal = Bit(start=20)
        @test length(signal) == 1
    end
end

@testset "unsigned_signal" begin
    using CANalyze.Signals

    @testset "unsigned_signal_1" begin
        signal = Signals.Unsigned(0, 8, 1.0, 0.0, :little_endian)
        @test true
    end

    @testset "unsigned_signal_2" begin
        signal = Signals.Unsigned(start=0, length=8, factor=1.0, offset=0.0,
                                  byte_order=:little_endian)
        @test true
    end

    @testset "unsigned_signal_3" begin
        signal = Signals.Unsigned{Float16}(0, 8)
        @test true
    end

    @testset "unsigned_signal_4" begin
        signal = Signals.Unsigned{Float16}(start=0, length=8)
        @test true
    end

    @testset "unsigned_signal_5" begin
        @test_throws DomainError Signals.Unsigned{Float16}(start=0, length=0)
    end

    @testset "unsigned_signal_6" begin
        @test_throws DomainError Signals.Unsigned{Float16}(start=0, length=0,
                                                           byte_order=:mixed_endian)
    end

    @testset "start_1" begin
        signal = Signals.Unsigned(23, 8, 1.0, 0.0, :little_endian)
        @test start(signal) == 23
    end

    @testset "length_1" begin
        signal = Signals.Unsigned(0, 8, 1.0, 0.0, :little_endian)
        @test length(signal) == 8
    end

    @testset "factor_1" begin
        signal = Signals.Unsigned(0, 8, 1.0, 0.0, :little_endian)
        @test factor(signal) == 1
    end

    @testset "offset_1" begin
        signal = Signals.Unsigned(0, 8, 1.0, 1337, :little_endian)
        @test offset(signal) == 1337
    end

    @testset "byte_order_1" begin
        signal = Signals.Unsigned(0, 8, 1.0, 0.0, :little_endian)
        @test byte_order(signal) == :little_endian
    end

    @testset "byte_order_2" begin
        signal = Signals.Unsigned(0, 8, 1.0, 0.0, :big_endian)
        @test byte_order(signal) == :big_endian
    end
end

@testset "signed_signal" begin
    using CANalyze.Signals

    @testset "signed_signal_1" begin
        signal = Signals.Signed(0, 8, 1.0, 0.0, :little_endian)
        @test true
    end

    @testset "signed_signal_2" begin
        signal = Signals.Signed(start=0, length=8, factor=1.0, offset=0.0,
                                  byte_order=:little_endian)
        @test true
    end

    @testset "signed_signal_3" begin
        signal = Signals.Signed{Float16}(0, 8)
        @test true
    end

    @testset "signed_signal_4" begin
        signal = Signals.Signed{Float16}(start=0, length=8)
        @test true
    end

    @testset "signed_signal_5" begin
        @test_throws DomainError Signals.Signed{Float16}(start=0, length=0)
    end

    @testset "signed_signal_6" begin
        @test_throws DomainError Signals.Signed{Float16}(start=0, length=0,
                                                         byte_order=:mixed_endian)
    end

    @testset "start_1" begin
        signal = Signals.Signed(23, 8, 1.0, 0.0, :little_endian)
        @test start(signal) == 23
    end

    @testset "length_1" begin
        signal = Signals.Signed(0, 8, 1.0, 0.0, :little_endian)
        @test length(signal) == 8
    end

    @testset "factor_1" begin
        signal = Signals.Signed(0, 8, 1.0, 0.0, :little_endian)
        @test factor(signal) == 1
    end

    @testset "offset_1" begin
        signal = Signals.Signed(0, 8, 1.0, 1337, :little_endian)
        @test offset(signal) == 1337
    end

    @testset "byte_order_1" begin
        signal = Signals.Signed(0, 8, 1.0, 0.0, :little_endian)
        @test byte_order(signal) == :little_endian
    end

    @testset "byte_order_2" begin
        signal = Signals.Signed(0, 8, 1.0, 0.0, :big_endian)
        @test byte_order(signal) == :big_endian
    end
end

@testset "float16_signal" begin
    using CANalyze.Signals

    @testset "float16_signal_1" begin
        signal = Signals.Float16Signal(0)
        @test true
    end

    @testset "float16_signal_2" begin
        signal = Signals.Float16Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test true
    end

    @testset "float16_signal_3" begin
        signal = Signals.Float16Signal(start=0, factor=1, offset=0,
                                       byte_order=:little_endian)
        @test true
    end

    @testset "start_1" begin
        signal = Signals.Float16Signal(start=42, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test start(signal) == 42
    end

    @testset "length_1" begin
        signal = Signals.Float16Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test length(signal) == 16
    end

    @testset "factor_1" begin
        signal = Signals.Float16Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test factor(signal) == 1
    end

    @testset "offset_1" begin
        signal = Signals.Float16Signal(start=0, factor=1.0, offset=1337,
                                       byte_order=:little_endian)
        @test offset(signal) == 1337
    end

    @testset "byte_order_1" begin
        signal = Signals.Float16Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test byte_order(signal) == :little_endian
    end

    @testset "byte_order_2" begin
        signal = Signals.Float16Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:big_endian)
        @test byte_order(signal) == :big_endian
    end
end

@testset "float32_signal" begin
    using CANalyze.Signals

    @testset "float32_signal_1" begin
        signal = Signals.Float32Signal(0)
        @test true
    end

    @testset "float32_signal_2" begin
        signal = Signals.Float32Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test true
    end

    @testset "float32_signal_3" begin
        signal = Signals.Float32Signal(start=0, factor=1, offset=0,
                                       byte_order=:little_endian)
        @test true
    end

    @testset "start_1" begin
        signal = Signals.Float32Signal(start=42, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test start(signal) == 42
    end

    @testset "length_1" begin
        signal = Signals.Float32Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test length(signal) == 32
    end

    @testset "factor_1" begin
        signal = Signals.Float32Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test factor(signal) == 1
    end

    @testset "offset_1" begin
        signal = Signals.Float32Signal(start=0, factor=1.0, offset=1337,
                                       byte_order=:little_endian)
        @test offset(signal) == 1337
    end

    @testset "byte_order_1" begin
        signal = Signals.Float32Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test byte_order(signal) == :little_endian
    end

    @testset "byte_order_2" begin
        signal = Signals.Float32Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:big_endian)
        @test byte_order(signal) == :big_endian
    end
end

@testset "float64_signal" begin
    using CANalyze.Signals

    @testset "float64_signal_1" begin
        signal = Signals.Float64Signal(0)
        @test true
    end

    @testset "float64_signal_2" begin
        signal = Signals.Float64Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test true
    end

    @testset "float64_signal_3" begin
        signal = Signals.Float64Signal(start=0, factor=1, offset=0,
                                       byte_order=:little_endian)
        @test true
    end

    @testset "start_1" begin
        signal = Signals.Float64Signal(start=42, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test start(signal) == 42
    end

    @testset "length_1" begin
        signal = Signals.Float64Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test length(signal) == 64
    end

    @testset "factor_1" begin
        signal = Signals.Float64Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test factor(signal) == 1
    end

    @testset "offset_1" begin
        signal = Signals.Float64Signal(start=0, factor=1.0, offset=1337,
                                       byte_order=:little_endian)
        @test offset(signal) == 1337
    end

    @testset "byte_order_1" begin
        signal = Signals.Float64Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:little_endian)
        @test byte_order(signal) == :little_endian
    end

    @testset "byte_order_2" begin
        signal = Signals.Float64Signal(start=0, factor=1.0, offset=0.0,
                                       byte_order=:big_endian)
        @test byte_order(signal) == :big_endian
    end
end

@testset "float_signal" begin
    using CANalyze.Signals

    @testset "float_signal_1" begin
        signal = Signals.FloatSignal(start=0, factor=2, offset=-1337,
                                     byte_order=:big_endian)
        @test true
    end

end

@testset "raw_signal" begin
    using CANalyze.Signals

    @testset "raw_signal_1" begin
        signal = Signals.Raw(0, 8, :little_endian)
        @test true
    end

    @testset "raw_signal_2" begin
        signal = Signals.Raw(start=0, length=8, byte_order=:little_endian)
        @test true
    end

    @testset "raw_signal_3" begin
        @test_throws DomainError Signals.Raw(start=0, length=0, byte_order=:little_endian)
    end

    @testset "raw_signal_4" begin
        @test_throws DomainError Signals.Raw(start=0, length=1, byte_order=:mixed_endian)
    end

    @testset "start_1" begin
        signal = Signals.Raw(start=42, length=8, byte_order=:little_endian)
        @test start(signal) == 42
    end

    @testset "length_1" begin
        signal = Signals.Raw(start=0, length=23, byte_order=:little_endian)
        @test length(signal) == 23
    end

    @testset "byte_order_1" begin
        signal = Signals.Raw(start=0, length=8, byte_order=:little_endian)
        @test byte_order(signal) == :little_endian
    end

    @testset "byte_order_2" begin
        signal = Signals.Raw(start=0, length=8, byte_order=:big_endian)
        @test byte_order(signal) == :big_endian
    end
end

@testset "named_signal" begin
    using CANalyze.Signals

    @testset "named_signal_1" begin
        s = Signals.Raw(0, 8, :little_endian)
        signal = Signals.NamedSignal("ABC", nothing, nothing, s)
        @test true
    end

    @testset "named_signal_2" begin
        s = Signals.Raw(0, 8, :little_endian)
        signal = Signals.NamedSignal(name="ABC", unit=nothing, default=nothing,
                                     signal=s)
        @test true
    end

    @testset "named_signal_3" begin
        s = Signals.Raw(0, 8, :little_endian)
        @test_throws DomainError Signals.NamedSignal(name="",
                                                     unit=nothing,
                                                     default=nothing,
                                                     signal=s)
    end

    @testset "name_1" begin
        s = Signals.Raw(0, 8, :little_endian)
        signal = Signals.NamedSignal(name="ABC", unit=nothing, default=nothing,
                                     signal=s)
        @test name(signal) == "ABC"
    end

    @testset "unit_1" begin
        s = Signals.Raw(0, 8, :little_endian)
        signal = Signals.NamedSignal(name="ABC", unit=nothing, default=nothing,
                                     signal=s)
        @test unit(signal) == nothing
    end

    @testset "unit_2" begin
        s = Signals.Raw(0, 8, :little_endian)
        signal = Signals.NamedSignal(name="ABC", unit="Ah", default=nothing,
                                     signal=s)
        @test unit(signal) == "Ah"
    end

    @testset "default_1" begin
        s = Signals.Raw(0, 8, :little_endian)
        signal = Signals.NamedSignal(name="ABC", unit="Ah", default=nothing,
                                     signal=s)
        @test default(signal) == nothing
    end

    @testset "default_2" begin
        s = Signals.Raw(0, 8, :little_endian)
        signal = Signals.NamedSignal(name="ABC", unit="Ah", default=UInt(1337),
                                     signal=s)
        @test default(signal) == 1337
    end

    @testset "signal_1" begin
        s = Signals.Raw(0, 8, :little_endian)
        signal = Signals.NamedSignal(name="ABC", unit="Ah", default=nothing,
                                     signal=s)
        @test Signals.signal(signal) == s
    end
end

@testset "bits" begin
    using CANalyze.Signals

    @testset "bit_1" begin
        signal = Bit(42)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(42)
    end

    @testset "unsigned_1" begin
        signal = Signals.Unsigned(7, 5, 1.0, 0.0, :little_endian)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(7, 8, 9, 10, 11)
    end

    @testset "unsigned_2" begin
        signal = Signals.Unsigned(7, 5, 1.0, 0.0, :big_endian)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(7, 6, 5, 4, 3)
    end

    @testset "signed_1" begin
        signal = Signals.Signed(7, 5, 1.0, 0.0, :little_endian)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(7, 8, 9, 10, 11)
    end

    @testset "signed_2" begin
        signal = Signals.Signed(3, 5, 1.0, 0.0, :big_endian)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(3, 2, 1, 0, 15)
    end

    @testset "float16_1" begin
        signal = Signals.Float16Signal(0; byte_order=:little_endian)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(Set{UInt16}([i for i=0:15]))
    end

    @testset "float16_2" begin
        signal = Signals.Float16Signal(0; byte_order=:big_endian)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17)
    end

    @testset "float32_1" begin
        signal = Signals.Float32Signal(0; byte_order=:little_endian)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(Set{UInt16}([i for i=0:31]))
    end

    @testset "float32_2" begin
        signal = Signals.Float32Signal(39; byte_order=:big_endian)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(Set{UInt16}([i for i=32:63]))
    end

    @testset "float64_1" begin
        signal = Signals.Float64Signal(0; byte_order=:little_endian)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(Set{UInt16}([i for i=0:63]))
    end

    @testset "float64_2" begin
        signal = Signals.Float64Signal(7; byte_order=:big_endian)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(Set{UInt16}([i for i=0:63]))
    end

    @testset "named_signal_1" begin
        s = Signals.Float64Signal(7; byte_order=:big_endian)
        signal = Signals.NamedSignal("ABC", nothing, nothing, s)
        bits = Signals.Bits(signal)
        @test bits == Signals.Bits(Set{UInt16}([i for i=0:63]))
    end

end

@testset "share_bits" begin
    using CANalyze.Signals

    @testset "share_bits_1" begin
        sig1 = Signals.Float16Signal(0; byte_order=:little_endian)
        sig2 = Signals.Float16Signal(0; byte_order=:little_endian)

        bits1 = Signals.Bits(sig1)
        bits2 = Signals.Bits(sig2)
        @test Signals.share_bits(bits1, bits2)
    end

    @testset "share_bits_2" begin
        sig1 = Signals.Float16Signal(0; byte_order=:little_endian)
        sig2 = Signals.Float16Signal(16; byte_order=:little_endian)

        bits1 = Signals.Bits(sig1)
        bits2 = Signals.Bits(sig2)
        @test !Signals.share_bits(bits1, bits2)
    end
end

@testset "overlap" begin
    using CANalyze.Signals

    @testset "overlap_1" begin
        sig1 = Signals.Float16Signal(0; byte_order=:little_endian)
        sig2 = Signals.Float16Signal(0; byte_order=:little_endian)

        @test Signals.overlap(sig1, sig2)
    end

    @testset "overlap_2" begin
        sig1 = Signals.Float16Signal(0; byte_order=:little_endian)
        sig2 = Signals.Float16Signal(16; byte_order=:little_endian)

        @test !Signals.overlap(sig1, sig2)
    end
end

@testset "check" begin
    using CANalyze.Signals

    @testset "bit_1" begin
        signal = Signals.Bit(0)
        @test Signals.check(signal, UInt8(1))
    end

    @testset "bit_2" begin
        signal = Signals.Bit(8)
        @test !Signals.check(signal, UInt8(1))
    end

    @testset "unsigned_1" begin
        signal = Signals.Unsigned(7, 5, 1.0, 0.0, :little_endian)
        @test Signals.check(signal, UInt8(2))
    end

    @testset "unsigned_2" begin
        signal = Signals.Unsigned(7, 9, 1.0, 0.0, :big_endian)
        @test Signals.check(signal, UInt8(2))
    end

    @testset "signed_1" begin
        signal = Signals.Signed(7, 5, 1.0, 0.0, :little_endian)
        @test Signals.check(signal, UInt8(2))
    end

    @testset "signed_2" begin
        signal = Signals.Signed(7, 9, 1.0, 0.0, :big_endian)
        @test Signals.check(signal, UInt8(2))
    end

    @testset "float16_1" begin
        signal = Signals.Float16Signal(0; byte_order=:little_endian)
        @test Signals.check(signal, UInt8(2))
    end

    @testset "float16_2" begin
        signal = Signals.Float16Signal(0; byte_order=:big_endian)
        @test !Signals.check(signal, UInt8(2))
    end

    @testset "float32_1" begin
        signal = Signals.Float32Signal(0; byte_order=:little_endian)
        @test Signals.check(signal, UInt8(4))
    end

    @testset "float32_2" begin
        signal = Signals.Float32Signal(0; byte_order=:big_endian)
        @test !Signals.check(signal, UInt8(4))
    end

    @testset "float64_1" begin
        signal = Signals.Float64Signal(0; byte_order=:little_endian)
        @test Signals.check(signal, UInt8(8))
    end

    @testset "float64_2" begin
        signal = Signals.Float64Signal(0; byte_order=:big_endian)
        @test !Signals.check(signal, UInt8(8))
    end

    @testset "raw_1" begin
        signal = Signals.Raw(0, 64, :little_endian)
        @test Signals.check(signal, UInt8(8))
    end

    @testset "raw_2" begin
        signal = Signals.Raw(0, 64, :big_endian)
        @test Signals.check(signal, UInt8(9))
    end

    @testset "named_signal_1" begin
        s = Signals.Raw(0, 64, :big_endian)
        signal = Signals.NamedSignal("ABC", nothing, nothing, s)
        @test Signals.check(signal, UInt8(9))
    end
end

@testset "equal" begin
    using CANalyze.Signals

    @testset "bit_1" begin
        bit1 = Signals.Bit(20)
        bit2 = Signals.Bit(20)
        @test bit1 == bit2
    end

    @testset "bit_2" begin
        bit1 = Signals.Bit(20)
        bit2 = Signals.Bit(21)
        @test !(bit1 == bit2)
    end

    @testset "unsigned_1" begin
        sig1 = Signals.Unsigned(0, 8, 1, 0, :little_endian)
        sig2 = Signals.Unsigned(0, 8, 1, 0, :little_endian)
        @test sig1 == sig2
    end

    @testset "unsigned_2" begin
        sig1 = Signals.Unsigned(0, 8, 1, 0, :little_endian)
        sig2 = Signals.Unsigned(1, 8, 1, 0, :little_endian)
        @test !(sig1 == sig2)
    end

    @testset "unsigned_3" begin
        sig1 = Signals.Unsigned(0, 8, 1, 0, :little_endian)
        sig2 = Signals.Unsigned(0, 9, 1, 0, :little_endian)
        @test !(sig1 == sig2)
    end

    @testset "unsigned_4" begin
        sig1 = Signals.Unsigned(0, 8, 1, 0, :little_endian)
        sig2 = Signals.Unsigned(0, 8, 2, 0, :little_endian)
        @test !(sig1 == sig2)
    end

    @testset "unsigned_5" begin
        sig1 = Signals.Unsigned(0, 8, 1, 0, :little_endian)
        sig2 = Signals.Unsigned(0, 8, 1, -1, :little_endian)
        @test !(sig1 == sig2)
    end

    @testset "unsigned_6" begin
        sig1 = Signals.Unsigned(0, 8, 1, 0, :little_endian)
        sig2 = Signals.Unsigned(0, 8, 1, 0, :big_endian)
        @test !(sig1 == sig2)
    end
end


text:
# Regularize

export Regularize

"""
**Regularize**

    Regularize(f, ρ=1.0, a=0.0)

Given function `f`, and optional parameters `ρ` (positive) and `a`, returns
```math
g(x) = f(x) + \\tfrac{ρ}{2}\\|x-a\\|².
```
Parameter `a` can be either an array or a scalar, in which case it is subtracted component-wise from `x` in the above expression.
"""
struct Regularize{T <: ProximableFunction, S <: Real, A <: Union{Real, AbstractArray}} <: ProximableFunction
    f::T
    rho::S
    a::A
    function Regularize{T,S,A}(f::T, rho::S, a::A) where {T <: ProximableFunction, S <: Real, A <: Union{Real, AbstractArray}}
        if rho <= 0.0
            error("parameter `ρ` must be positive")
        else
            new(f, rho, a)
        end
    end
end

is_separable(f::Regularize) = is_separable(f.f)
is_prox_accurate(f::Regularize) = is_prox_accurate(f.f)
is_convex(f::Regularize) = is_convex(f.f)
is_smooth(f::Regularize) = is_smooth(f.f)
is_quadratic(f::Regularize) = is_quadratic(f.f)
is_generalized_quadratic(f::Regularize) = is_generalized_quadratic(f.f)
is_strongly_convex(f::Regularize) = true

Regularize(f::T, rho::S, a::A) where {T <: ProximableFunction, S <: Real, A <: AbstractArray} = Regularize{T, S, A}(f, rho, a)

Regularize(f::T, rho::S=one(S), a::S=zero(S)) where {T <: ProximableFunction, S <: Real} = Regularize{T, S, S}(f, rho, a)

function (g::Regularize)(x::AbstractArray{T}) where T <: RealOrComplex
    return g.f(x) + g.rho/2*norm(x .- g.a)^2
end

function gradient!(y::AbstractArray{T}, g::Regularize, x::AbstractArray{T}) where T <: RealOrComplex
    v = gradient!(y, g.f, x)
    y .+= g.rho*(x .- g.a)
    return v + g.rho/2*norm(x .- g.a)^2
end

function prox!(y::AbstractArray{T}, g::Regularize, x::AbstractArray{T}, gamma::Union{R, AbstractArray{R}}=R(1)) where {R <: Real, T <: RealOrComplex{R}}
    gr = g.rho*gamma
    gr2 = 1.0 ./ (1.0 .+ gr)
    v = prox!(y, g.f, gr2.*(x .+ gr.*g.a), gr2.*gamma)
    return v + g.rho/2*norm(y .- g.a)^2
end

fun_name(f::Regularize) = string("Regularized ", fun_name(f.f))
fun_dom(f::Regularize) = fun_dom(f.f)
fun_expr(f::Regularize) = string(fun_expr(f.f), "+(ρ/2)||x-a||²")
fun_params(f::Regularize) = "ρ = $(f.rho), a = $( typeof(f.a) <: Real ? f.a : typeof(f.a) )"

function prox_naive(g::Regularize, x::AbstractArray{T}, gamma::Union{R, AbstractArray{R}}=R(1)) where {R <: Real, T <: RealOrComplex{R}}
    y, v = prox_naive(g.f, x./(1.0 .+ gamma.*g.rho) .+ g.a./(1.0./(gamma.*g.rho) .+ 1.0), gamma./(1.0 .+ gamma.*g.rho))
    return y, v + g.rho/2*norm(y .- g.a)^2
end


text:
@symbol_func function epsilon_b(cur_reactor::AbstractReactor)
  cur_epsilon = a(cur_reactor)

  cur_epsilon += b(cur_reactor)

  cur_epsilon /= safe_symbol(cur_reactor, :R_0)

  cur_epsilon
end


text:
#InspectDR: show functions
#-------------------------------------------------------------------------------

function Base.show(io::IO, plot::Plot2D)
	n = length(plot.strips)
	print(io, "Plot2D(\"$(plot.annotation.title)\", $n strips)")
end

function Base.show(io::IO, mplot::Multiplot)
	n = length(mplot.subplots)
	print(io, "Multiplot(\"$(mplot.title)\", $n subplots)")
end

if GtkAvailable

function Base.show(io::IO, w::PlotWidget)
	plot = w.src
	n = length(plot.strips)
	print(io, "PlotWidget(\"$(plot.annotation.title)\", $n strips)")
end

function Base.show(io::IO, gplot::GtkPlot)
	mplot = gplot.src
	n = length(mplot.subplots)
	print(io, "GtkPlot(\"$(mplot.title)\", $n subplots)")
end

end

#Last line


text:
using WAV

f, fs, nbits, opt = wavread("audio.wav")
periods = round(Int, floor(fs / 1024))
E = fill(0.0, periods)

i_0 = 1
for period = 1:periods
    e_instant = 0
    for k = i_0:(i_0 + 1023)
        e_instant += (f[k,:][1])^2 + (f[k,:][2])^2
    end

    e_local = 0
    for i = 1:periods
        e_local += (E[i])^2
    end
    e_local /= periods

    variance = 0
    for i = 1:periods
        variance += (E[i] - e_local)^2
    end
    variance = sqrt(variance/periods)
    c = (-0.0025714 * variance) + 1.5142857

    E = circshift(E, 1)
    E[1] = e_instant

    if e_instant > c * e_local
        println(period, ": ", e_instant, " > ", c * e_local)
    end
    i_0 += 1024
end

max_stars_repo_name: broluwo/ciett

max_issues_repo_name: broluwo/ciett

max_forks_repo_name: broluwo/ciett


text:
module CUDAint

using ..CUDA

import ..Flux: Flux
using ChainRulesCore
import NNlib, NNlibCUDA

include("cudnn.jl")

end


text:
"""
    matrix_projection_irr([hom::InducedActionHomomorphism, ]χ::Character)
Compute matrix projection associated to the irreducible character `χ`.

If the homomorphism is not passed, the dimension `d` of the projection is
derived from `conjugacy_classes(χ)`. E.g. if `conjugacy_classes(χ)` consist
of permutations of degree `d` (i.e. acting naturally on the set `1:d`) the
result will be a matrix of size `(d,d)`.

If the homomorphism is passed, the dimension will be derived in similar
manner from the elements of the image of the homomorphism.
"""
function matrix_projection_irr(χ::Character)
    @assert isirreducible(χ)
    mproj = matrix_projection_irr(collect(values(χ)), conjugacy_classes(χ))
    mproj .*= degree(χ) // sum(length, conjugacy_classes(χ)) # χ(1)/order(G)
    return mproj
end

function matrix_projection_irr(
    vals,
    ccls::AbstractVector{<:AbstractOrbit{<:PermutationGroups.AbstractPerm}},
)
    dim = degree(first(first(ccls)))
    result = zeros(eltype(vals), dim, dim)

    for (val, cc) in zip(vals, ccls)
        for g in cc
            for i in 1:dim
                result[i, i^g] += val
            end
        end
    end

    return result
end

function matrix_projection_irr(
    vals,
    ccls::AbstractVector{<:AbstractOrbit{<:AbstractMatrix}},
)
    # TODO: call to inv(Matrix(g)) is a dirty hack, since if `g`
    # is given by a sparse matrix `inv(g)` will fail.
    return sum(val .* sum(g -> inv(Matrix(g)), cc) for (val, cc) in zip(vals, ccls))
end

## versions with InducedActionHomomorphisms

function matrix_projection_irr(hom::InducedActionHomomorphism, χ::Character{T}) where T
    @assert isirreducible(χ)
    mproj = matrix_projection_irr(hom, collect(values(χ)), conjugacy_classes(χ))
    mproj .*= degree(χ) // sum(length, conjugacy_classes(χ)) # χ(1)/order(G)
    return eltype(mproj) == T ? mproj : T.(mproj)
end

function matrix_projection_irr(
    hom::InducedActionHomomorphism{<:ByPermutations},
    class_values,
    conjugacy_cls,
    )
    dim = degree(induce(hom, first(first(conjugacy_cls))))
    result = zeros(eltype(class_values), dim, dim)
    for (val, ccl) in zip(class_values, conjugacy_cls)
        for g in ccl
            h = induce(hom, g)
            for i in 1:dim
                result[i, i^h] += val
            end
        end
    end
    return result
end

function matrix_projection_irr(
    hom::InducedActionHomomorphism{<:ByLinearTransformation},
    class_values,
    conjugacy_cls,
)
    return sum(
        val .* sum(g -> induce(hom, inv(g)), cc)
        for (val, cc) in zip(class_values, conjugacy_cls)
    )
end

function matrix_projection(χ::Character{T}) where T
    tbl = table(χ)
    res = sum(
        c .* matrix_projection_irr(ψ)
        for (c, ψ) in zip(constituents(χ), irreducible_characters(tbl)) if !iszero(c)
    )
    return eltype(res) == T ? res : T.(res)
end

function matrix_projection(hom::InducedActionHomomorphism, χ::Character{T}) where T
    tbl = table(χ)
    res = sum(
        c .* matrix_projection_irr(hom, ψ)
        for (c, ψ) in zip(constituents(χ), irreducible_characters(tbl)) if !iszero(c)
    )
    return eltype(res) == T ? res : T.(res)
end

function matrix_projection(
    hom::InducedActionHomomorphism{<:ByPermutations},
    α::AlgebraElement,
    dim::Integer = length(features(hom)),
)
    result = zeros(eltype(α), dim, dim)
    b = basis(parent(α))

    @inbounds for (j, a) in StarAlgebras._nzpairs(StarAlgebras.coeffs(α))
        g = induce(hom, b[j])
        for i in 1:dim
            result[i, i^g] += a
        end
    end

    return result
end

function matrix_projection(
    hom::InducedActionHomomorphism{<:ByLinearTransformation},
    α::AlgebraElement,
    dim::Integer = length(features(hom)),
)

    result = zeros(Base._return_type(*, Tuple{eltype(α), coeff_type(action(hom))}), dim, dim)
    b = basis(parent(α))

    for (j, a) in StarAlgebras._nzpairs(StarAlgebras.coeffs(α))
        result += a*induce(hom, inv(b[j]))
    end

    return result
end

function matrix_projection(
    α::AlgebraElement{<:StarAlgebra{<:PermutationGroups.AbstractPermutationGroup}},
    dim::Integer = degree(parent(parent(α)))
)
    result = zeros(eltype(α), dim, dim)
    b = basis(parent(α))

    @inbounds for (j, a) in StarAlgebras._nzpairs(StarAlgebras.coeffs(α))
        g = b[j]
        for i in 1:dim
            result[i, i^g] += a
        end
    end

    return result
end

image_basis!(A::AbstractMatrix) = row_echelon_form!(A)

function image_basis!(A::AbstractMatrix{T}) where {T<:AbstractFloat}
    A, p = row_echelon_form!(A)
    fact = svd!(Matrix(@view A[1:length(p), :]))
    A_rank = sum(fact.S .> maximum(size(A)) * eps(T))
    return fact.Vt, 1:A_rank
end

function image_basis!(A::AbstractMatrix{T}) where {T<:Complex}
    fact = svd!(A)
    A_rank = sum(fact.S .> maximum(size(A)) * 2eps(real(T)))
    return fact.Vt, 1:A_rank
end

image_basis(A::AbstractMatrix) =
    ((m, p) = image_basis!(deepcopy(A)); m[1:length(p), :])

function image_basis(χ::Character)
    mpr = isirreducible(χ) ? matrix_projection_irr(χ) : matrix_projection(χ)
    image, pivots = image_basis!(mpr)
    return image[1:length(pivots), :]
end

function image_basis(hom::InducedActionHomomorphism, χ::Character)
    mpr = isirreducible(χ) ? matrix_projection_irr(hom, χ) : matrix_projection(hom, χ)
    image, pivots = image_basis!(mpr)
    return image[1:length(pivots), :]
end

function image_basis(α::AlgebraElement)
    image, pivots = image_basis!(matrix_projection(α))
    return image[1:length(pivots), :]
end

function image_basis(hom::InducedActionHomomorphism, α::AlgebraElement)
    image, pivots = image_basis!(matrix_projection(hom, α))
    return image[1:length(pivots), :]
end


text:
@testset "latent_gp" begin
    gp = GP(SqExponentialKernel())
    x = rand(10)
    y = rand(10)

    lgp = LatentGP(gp, x -> MvNormal(x, 0.1), 1e-5)
    @test lgp isa LatentGP
    @test lgp.f isa AbstractGPs.AbstractGP
    @test lgp.Σy isa Real

    lfgp = lgp(x)
    @test lfgp isa AbstractGPs.LatentFiniteGP
    @test lfgp.fx isa AbstractGPs.FiniteGP
    @test length(lfgp) == length(x)

    f = rand(10)
    @test logpdf(lfgp, (f=f, y=y)) isa Real
    @test rand(lfgp) isa NamedTuple{(:f, :y)}
end


text:
# Copyright (c) 2014, Dreki Þórgísl <dreki@billo.systems>
#               2014, Bence Golda <bence@cursorinsight.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#  * Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#  * Neither the name of the copyright holders nor the names of its
#    contributors may be used to endorse or promote products derived from this
#    software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
module Decode

using ErlPort.Exceptions

export decode, decode_with_tail,
decodeterm, decodeatom,
decodesmallint, decodeint, decodenewfloat,
decodesmallbigint, decodelargebigint,
decodemap, decodefloat,
decodebin,
decodenil, decodestring, decodelist,
decodesmalltuple, decodelargetuple,
decompressterm,
size1unpack, size2unpack, size4unpack # for tests only XXX: do we really need this here?

include("Tags.jl")
include("Util.jl")

function decode(bytes::AbstractArray{UInt8,1})
    (result, acc) = decode(view(bytes, 1:length(bytes)))
    if length(acc) > 0
        throw(IncompleteData(acc))
    end
    return result
end

function decode_with_tail(bytes::AbstractArray{UInt8, 1})
    decode(view(bytes, 1:length(bytes)))
end

function decode(bytes::SubArray{UInt8})
    lencheck(bytes, 1)
    if bytes[1] != version
        throw(UnknownProtocolVersion(bytes[1]))
    end
    if length(bytes) >= 2 && bytes[2] == compressedtag
        throw(NotImplemented())
    end

    return decodeterm(view(bytes, 2:length(bytes)))
end

function decode(unsupported)
    throw(UnsupportedType(unsupported))
end

function decodeterm(bytes::AbstractArray{UInt8,1})
    decodeterm(view(bytes, 1:length(bytes)))
end

function decodeterm(bytes::SubArray{UInt8})
    lencheck(bytes, 1)
    tag = bytes[1]
    if tag == atomtag
        return decodeatom(bytes)
    elseif tag == niltag
        return decodenil(bytes)
    elseif tag == stringtag
        return decodestring(bytes)
    elseif tag == smalltupletag
        return decodesmalltuple(bytes)
    elseif tag == largetupletag
        return decodelargetuple(bytes)
    elseif tag == listtag
        return decodelist(bytes)
    elseif tag == smallinttag
        return decodesmallint(bytes)
    elseif tag == inttag
        return decodeint(bytes)
    elseif tag == bintag
        return decodebin(bytes)
    elseif tag == newfloattag
        return decodenewfloat(bytes)
    elseif tag == smallbiginttag
        return decodesmallbigint(bytes)
    elseif tag == largebiginttag
        return decodelargebigint(bytes)
    elseif tag == maptag
        return decodemap(bytes)
    elseif tag == floattag
        return decodefloat(bytes)
    else
        throw(UnsupportedData(bytes))
    end
end

function decodeterm(acc::Array, byte::UInt8)
    vcat(acc, decodeterm([byte]))
end

function decodeatom(bytes::AbstractArray{UInt8,1})
    decodeatom(view(bytes, 1:length(bytes)))
end

function decodeatom(bytes::SubArray{UInt8})
    len = lencheck(bytes, 3)
    unpackedlen = lencheck(len, size2unpack(view(bytes, 2:3)) + 3, bytes)
    name = bytes[4:unpackedlen]
    if name == b"true"
        return (true, view(bytes, unpackedlen+1:length(bytes)))
    elseif name == b"false"
        return (false, view(bytes, unpackedlen+1:length(bytes)))
    elseif name == b"undefined"
        return (nothing, view(bytes, unpackedlen+1:length(bytes)))
    elseif name == b"nan"
        return (NaN, view(bytes, unpackedlen+1:length(bytes)))
    else
        return (Symbol(name), view(bytes, unpackedlen+1:length(bytes)))
    end
end

function decodenil(bytes::AbstractArray{UInt8,1})
    decodenil(view(bytes, 1:length(bytes)))
end

function decodenil(bytes::SubArray{UInt8})
    lencheck(bytes, 1)
    return ([], view(bytes, 2:length(bytes)))
end

function decodestring(bytes::AbstractArray{UInt8,1})
    decodestring(view(bytes, 1:length(bytes)))
end

function decodestring(bytes::SubArray{UInt8})
    len = lencheck(bytes, 3)
    unpackedlen = lencheck(len, size2unpack(view(bytes, 2:3)) + 3, bytes)
    (bytes[4:unpackedlen], view(bytes, unpackedlen+1:length(bytes)))
end

function decodesmallint(bytes::AbstractArray{UInt8,1})::Tuple{UInt8, Array{UInt8,1}}
    decodesmallint(view(bytes, 1:length(bytes)))
end

function decodesmallint(bytes::SubArray{UInt8})
    lencheck(bytes, 2)
    (int1unpack(bytes[2]), view(bytes, 3:length(bytes)))
end

function decodeint(bytes::AbstractArray{UInt8,1})
    decodeint(view(bytes, 1:length(bytes)))
end

function decodeint(bytes::SubArray{UInt8})
    lencheck(bytes, 5)
    (int4unpack(view(bytes, 2:5)), view(bytes, 6:length(bytes)))
end

function decodebin(bytes::AbstractArray{UInt8,1})
    decodebin(view(bytes, 1:length(bytes)))
end

function decodebin(bytes::SubArray{UInt8})
    len = lencheck(bytes, 5)
    unpackedlen = lencheck(len, size4unpack(view(bytes, 2:5)) + 5, bytes)
    (bytes[6:unpackedlen], view(bytes, unpackedlen+1:length(bytes)))
end

function decodenewfloat(bytes::AbstractArray{UInt8,1})
    decodenewfloat(view(bytes, 1:length(bytes)))
end

function decodenewfloat(bytes::SubArray{UInt8})
    lencheck(bytes, 9)
    (floatunpack(view(bytes, 2:9)), view(bytes, 10:length(bytes)))
end

function decodelist(bytes::AbstractArray{UInt8,1})
    decodelist(view(bytes, 1:length(bytes)))
end

function decodelist(bytes::SubArray{UInt8})
    lencheck(bytes, 5)
    (results, tail) = converttoarray(size4unpack(view(bytes, 2:5)), view(bytes, 6:length(bytes)))
    # XXX mojombo's BERT (https://github.com/mojombo/bert) does the same -- it
    # skips the improper part in lists (or throws a RuntimeError)
    (skipped, tail) = decodeterm(tail)
    (results, tail)
end

function converttoarray(len::UInt64, tail::Array{UInt8,1})
    converttoarray(len::UInt64, view(tail, 1:length(tail)))
end

function converttoarray(len::UInt64, tail::SubArray{UInt8})
    local results = Vector{Any}()
    if len > 0
        results = map(0:1:len-1) do i
            (term, tail) = decodeterm(tail)
            term
        end
    end
    (results, tail)
end

function decodesmalltuple(bytes::AbstractArray{UInt8,1})
    decodesmalltuple(view(bytes, 1:length(bytes)))
end

function decodesmalltuple(bytes::SubArray{UInt8})
    lencheck(bytes, 2)
    converttotuple(size1unpack(bytes[2]), view(bytes, 3:length(bytes)))
end

function decodelargetuple(bytes::AbstractArray{UInt8,1})
    decodelargetuple(view(bytes, 1:length(bytes)))
end

function decodelargetuple(bytes::SubArray{UInt8})
    lencheck(bytes, 5)
    converttotuple(size4unpack(view(bytes, 2:5)), view(bytes, 6:length(bytes)))
end

function converttotuple(len::UInt64, tail::SubArray{UInt8})
    if len < 1
        return( (), tail )
    end
    (results, tail) = converttoarray(len, tail)
    (tuple(results...), tail)
end

function decodesmallbigint(bytes::AbstractArray{UInt8,1})
    decodesmallbigint(view(bytes, 1:length(bytes)))
end

function decodesmallbigint(bytes::SubArray{UInt8})
    len = lencheck(bytes, 3)
    bisize = size1unpack(bytes[2])
    lencheck(len, bisize + 3, bytes)
    result = computebigint(bisize, view(bytes, 4:bisize+3), bytes[3])
    (result, view(bytes, bisize+4:length(bytes)))
end

function decodelargebigint(bytes::AbstractArray{UInt8,1})
    decodelargebigint(view(bytes, 1:length(bytes)))
end

function decodelargebigint(bytes::SubArray{UInt8})
    len = lencheck(bytes, 6)
    bisize = size4unpack(view(bytes, 2:5))
    lencheck(len, bisize + 6, bytes)
    result = computebigint(bisize, view(bytes, 7:bisize+6), bytes[6])
    (result, view(bytes, bisize+7:length(bytes)))
end

function computebigint(len::UInt64, coefficients::AbstractArray{UInt8,1}, sign::UInt8)
    computebigint(len::UInt64, view(coefficients, 1:length(coefficients)), sign)
end

function computebigint(len::UInt64, coefficients::SubArray{UInt8}, sign::UInt8)
    result = convert(Int64, sum((256 .^ collect(0:len-1)) .* coefficients))
    return(sign > 0 ? -result : result)
end

function decodemap(bytes::AbstractArray{UInt8,1})
    decodemap(view(bytes, 1:length(bytes)))
end

function decodemap(bytes::SubArray{UInt8})
    len = lencheck(bytes, 5)
    bisize = size4unpack(view(bytes, 2:5))
    result = Dict()

    bytes = view(bytes, 6:length(bytes))
    i = 1
    while i <= bisize
        (key, bytes) = decodeterm(bytes)
        (value, bytes) = decodeterm(bytes)
        result[key] = value
        i += 1
    end

    (result, bytes)
end

function decodefloat(bytes::AbstractArray{UInt8,1})::Tuple{Float64, Vector{UInt8}}
    decodefloat(view(bytes, 1:length(bytes)))
end

function decodefloat(bytes::SubArray{UInt8})
    len = lencheck(bytes, 9)
    result = reinterpret(Float64, parse(UInt64, bytes2hex(view(bytes, 2:9)), base =16))
    (result, view(bytes, 10:length(bytes)))
end

end


text:
function scale(num::Int64, input::Float32)
    u = 1.0/(2*(num-1))
    for i in 1:2:2*(num-1)
        if input<=i*u
            return (i-1)*u
        elseif i*u<input<=(i+1)*u
            return (i+1)*u
        end
    end
end

function Spiking!(input::Array{Float32}, spiking_trains::Array{Float32}, scales::Int64, r, T)
    V₊ = maximum(input)
    V₋ = minimum(input)
    @batch for i in 1:length(input)
        freq = Int64(ceil((r-T-1)*scale(scales, (input[i]-V₋)/(V₊-V₋))+T+1))

        #=@avx=# for t in freq:freq:T
            spiking_trains[t,i] = 1
        end
    end

    θ = 0.0
    @avxt for t in 1:T
        s = 0
        for i in 1:length(input)
            s += spiking_trains[t,i]
        end
        θ = max(θ, s)
    end
    #println(θ)
    return θ
end


text:
#TODO: CHANGE NAME
function pricer(mcProcess::FinancialMonteCarlo.BaseProcess, StrikeVec::Array{U, 1}, zero_rate::FinancialMonteCarlo.AbstractZeroRateCurve, T::num, method::CarrMadanLewisMethod, ::FinancialMonteCarlo.CudaMode) where {U <: Number, num <: Number}
    Npow = method.Npow
    N = 2^Npow
    S0 = mcProcess.underlying.S0
    A = method.A
    d = FinancialMonteCarlo.integral(FinancialMonteCarlo.dividend(mcProcess), T) / T
    r = FinancialMonteCarlo.integral(zero_rate.r, T) / T
    cf = FinancialFFT.CharactheristicFunction(mcProcess, T)
    corr = (r - d) * T - FinancialFFT.CharactheristicExponent(-1im, mcProcess, T)
    CharFunc(v::num) where {num <: Number} = cf(v) * exp(v * 1im * corr)
    dx = A / N
    x = collect(0:(N-1)) * dx
    x[1] = 1e-312
    weights_ = @. 3 + (-1)^((0:(N-1)) + 1)
    @views weights_[1] = 1
    @views weights_[N] = 1
    weights_cu = cu(weights_)
    x_cu = cu(x)
    dk = 2 * pi / A
    b = N * dk / 2
    ks = -b .+ dk * (0:(N-1))
    integrand = @. exp(-1im * b * x_cu) * CharFunc(x_cu - 0.5 * 1im) / (x_cu^2 + 0.25) * weights_cu * dx / 3
    fft!(integrand)
    integral_value = collect(@. real_mod(integrand) / pi)

    spline_cub = CubicSplineInterpolation(ks, integral_value)
    prices = @. S0 - sqrt(S0 * StrikeVec) * exp(-(r - d) * T) * spline_cub(log(StrikeVec / S0))
    return prices * exp(-d * T)
end


text:
import HTTP

const LIBRDKAFKA_REPO = "https://github.com/edenhill/librdkafka/"
# const RELEASE_URL = "https://github.com/edenhill/librdkafka/archive/v0.11.4-adminapi-post1.tar.gz"

# linux-only
cd(@__DIR__) do
    rm("librdkafka"; recursive=true)
    run(`git clone --depth 1 -b master $LIBRDKAFKA_REPO librdkafka`)
    cd("librdkafka") do
        run(`./configure`)
        run(`make`)
    end
    cp("librdkafka/src/librdkafka.so.1", "librdkafka.so"; force=true )
end

# HTTP.open("GET", RELEASE_URL) do http
#     print(typeof(http))
#     # open(`vlc -q --play-and-exit --intf dummy -`, "w") do vlc
#     #     write(vlc, http)
#     # end
# end


text:
module SDL

using SimpleDirectMediaLayer

# Clear with a specific color provided as RGB
function clear_with_color(window, r, g, b)
    renderer = SimpleDirectMediaLayer.GetRenderer(window)
    SimpleDirectMediaLayer.SetRenderDrawColor(renderer, r, g, b, 0)
    SimpleDirectMediaLayer.RenderClear(renderer)
    SimpleDirectMediaLayer.RenderPresent(renderer)
end

# Clear window with white color
clear(window) = clear_with_color(window, 255, 255, 255)

function main()
    SimpleDirectMediaLayer.init()

    # Ptr{SDL.Window}
    win = SimpleDirectMediaLayer.CreateWindow("my window",
                                          Int32(0), Int32(0),
                                          Int32(800), Int32(600),
                                          UInt32(SimpleDirectMediaLayer.WINDOW_OPENGL));

    # See https://wiki.libsdl.org/SDL_CreateRenderer
    SimpleDirectMediaLayer.CreateRenderer(win, Int32(-1), UInt32(0))

    # Change the color of the window gradually
    r, g, b = (0, 0, 0)
    for r in 255:255
        for g in 0:255
            clear_with_color(win, r, g, g)
            SimpleDirectMediaLayer.Delay(UInt32(20))
        end
    end

    # Wait a bit and finalize
    SimpleDirectMediaLayer.Delay(UInt32(3000))
    SimpleDirectMediaLayer.Quit()
end

main()

end # module

max_stars_repo_name: julitopower/JuliaLangAdventures

max_issues_repo_name: julitopower/JuliaLangAdventures

max_forks_repo_name: julitopower/JuliaLangAdventures


text:
using BinaryProvider # requires BinaryProvider 0.3.0 or later

# Parse some basic command-line arguments
const verbose = "--verbose" in ARGS
const prefix = Prefix(get([a for a in ARGS if a != "--verbose"], 1, joinpath(@__DIR__, "usr")))
products = [
    LibraryProduct(prefix, ["libpixman"], :libpixman),
]

# Download binaries from hosted location
bin_prefix = "https://github.com/JuliaBinaryWrappers/Pixman_jll.jl/releases/download/Pixman-v0.38.4+1"

# Listing of files generated by BinaryBuilder:
download_info = Dict(
    Linux(:aarch64, libc=:glibc) => ("$bin_prefix/Pixman.v0.38.4.aarch64-linux-gnu.tar.gz", "d0c3311012fbd05449d64d01fbb429ffd62136caee86e9eee4a792d7222c4edc"),
    Linux(:aarch64, libc=:musl) => ("$bin_prefix/Pixman.v0.38.4.aarch64-linux-musl.tar.gz", "1a6d8f0705b232bc375b7d8981475b91760c6c02e297ca8b1a5ee5c1477d82f1"),
    Linux(:armv7l, libc=:glibc, call_abi=:eabihf) => ("$bin_prefix/Pixman.v0.38.4.arm-linux-gnueabihf.tar.gz", "f799396e398ca5d7dc944c0c5c7752345b8c92be44d8babd987d0e579ae5bf52"),
    Linux(:armv7l, libc=:musl, call_abi=:eabihf) => ("$bin_prefix/Pixman.v0.38.4.arm-linux-musleabihf.tar.gz", "06ea92cc17cb7dccaf0b81699ecc1f560b0cf35a160f5268f544659a4b02cb44"),
    Linux(:i686, libc=:glibc) => ("$bin_prefix/Pixman.v0.38.4.i686-linux-gnu.tar.gz", "f2d8edb3e59dcedd0e7c41fd31fff8561b703b73000f4ae5b5e4fc4c2eb6caf7"),
    Linux(:i686, libc=:musl) => ("$bin_prefix/Pixman.v0.38.4.i686-linux-musl.tar.gz", "f20a2fbb52d4043c8615cd2d5d0f8bebf8f8620cbbc3552d88d91d3453be8e41"),
    Windows(:i686) => ("$bin_prefix/Pixman.v0.38.4.i686-w64-mingw32.tar.gz", "f0d6a8d30457d9d3ff99069d7d449be7f10742646e693b69273df22283a7abce"),
    Linux(:powerpc64le, libc=:glibc) => ("$bin_prefix/Pixman.v0.38.4.powerpc64le-linux-gnu.tar.gz", "18145abe2c4f8b78aae5b15071c214a8d9d3a7d4c4f460dc76c81847af5c3456"),
    MacOS(:x86_64) => ("$bin_prefix/Pixman.v0.38.4.x86_64-apple-darwin14.tar.gz", "ef915b1c1ebc0d6b3a61dc058dfecfec0cff05663f7288db83461862022a0c13"),
    Linux(:x86_64, libc=:glibc) => ("$bin_prefix/Pixman.v0.38.4.x86_64-linux-gnu.tar.gz", "cf3c82002dd3b15b47cb220eff021ee3008ed0499550d20de04b6a5b21d7e0c4"),
    Linux(:x86_64, libc=:musl) => ("$bin_prefix/Pixman.v0.38.4.x86_64-linux-musl.tar.gz", "67cb023d77223f0eecddaefcd13480722f8185c49ba3c911522d48a2ccce4b69"),
    FreeBSD(:x86_64) => ("$bin_prefix/Pixman.v0.38.4.x86_64-unknown-freebsd11.1.tar.gz", "57601a037623b7cda6414b209ba8886a4f34bb029a2de9ef0bcbf2848e4b371c"),
    Windows(:x86_64) => ("$bin_prefix/Pixman.v0.38.4.x86_64-w64-mingw32.tar.gz", "60a1ac4fbfd75d0191e75242137929afe377804f1eb92bf5d3e146c073751f4e"),
)

# Install unsatisfied or updated dependencies:
unsatisfied = any(!satisfied(p; verbose=verbose) for p in products)
dl_info = choose_download(download_info, platform_key_abi())
if dl_info === nothing && unsatisfied
    # If we don't have a compatible .tar.gz to download, complain.
    # Alternatively, you could attempt to install from a separate provider,
    # build from source or something even more ambitious here.
    error("Your platform (\"$(Sys.MACHINE)\", parsed as \"$(triplet(platform_key_abi()))\") is not supported by this package!")
end

# If we have a download, and we are unsatisfied (or the version we're
# trying to install is not itself installed) then load it up!
if unsatisfied || !isinstalled(dl_info...; prefix=prefix)
    # Download and install binaries
    install(dl_info...; prefix=prefix, force=true, verbose=verbose)
end

# Write out a deps.jl file that will contain mappings for our products
write_deps_file(joinpath(@__DIR__, "deps.jl"), products, verbose=verbose)


text:
"""

```
shellradius(i,step)
```

Compute the point in which the radius comprises half of the
volume of the shell.
"""
function shellradius(i,step)
  rmin = (i-1)*step
  return ( 0.5*( (rmin+step)^3 + rmin^3 ) )^(1/3)
end


text:
"""
    Despike{R}(reference::Function,n,k)
    (d::Despike)(q::Quantity)

Remove spikes from a Quantity

Despike applies a function (`reference`)
to a moving window of size `k` to compute
a reference time series.

Spikes are defined as those points lying `n` times
the standard deviation of the residuals away from
the reference time series.

What it does with the spikes depends on the
value of the type parameter `R`

`R` can be one of

- `:filter`: Replace the entire time series with the reference series
- `:reference`: Replace identified spikes with the reference series
- `:nan`: Replace spikes with NaN
"""
struct Despike{R}
    reference::Function
    n
    k
end

(d::Despike{:filter}){T<:Quantity}(q::T) = TidalFluxQuantities.filter_window(q,d.reference,d.k)

function (d::Despike{:reference}){T<:Quantity}(q::T)
    refQ = TidalFluxQuantities.filter_window(q,d.reference,d.k)
    res = quantity(q).-quantity(refQ)
    σ = std(res)
    idxs = find(abs.(res).>(d.n*σ))
    newQ = quantity(q)[:]
    newQ[idxs] = quantity(refQ)[idxs]
    T(times(q),newQ)
end

function (d::Despike{:nan}){T<:Quantity}(q::T)
    refQ = TidalFluxQuantities.filter_window(q,d.reference,d.k)
    res = quantity(q).-quantity(refQ)
    σ = std(res)
    idxs = find(abs.(res).>(d.n*σ))
    newQ = quantity(q)[:]
    newQ[idxs] = NaN
    T(times(q),newQ)
end

function threshold{T<:Quantity}(q::T,t,z)
    newQ = quantity(q)[:]
    newQ[newQ.>t] = z
    T(times(q),newQ)
end


text:
using Oceananigans.Operators: interpolation_code

struct Derivative{LX, LY, LZ, D, A, I, AD, G, T} <: AbstractOperation{LX, LY, LZ, G, T}
               ∂ :: D
             arg :: A
               ▶ :: I
      abstract_∂ :: AD
            grid :: G

    @doc """
        Derivative{LX, LY, LZ}(∂, arg, ▶, grid)

    Returns an abstract representation of the derivative `∂` on `arg`,
    and subsequent interpolation by `▶` on `grid`.
    """
    function Derivative{LX, LY, LZ}(∂::D, arg::A, ▶::I, abstract_∂::AD,
                                 grid::G) where {LX, LY, LZ, D, A, I, AD, G}
        T = eltype(grid)
        return new{LX, LY, LZ, D, A, I, AD, G, T}(∂, arg, ▶, abstract_∂, grid)
    end
end

@inline Base.getindex(d::Derivative, i, j, k) = d.▶(i, j, k, d.grid, d.∂, d.arg)

#####
##### Derivative construction
#####

"""Create a derivative operator `∂` acting on `arg` at `L∂`, followed by
interpolation to `L` on `grid`."""
function _derivative(L, ∂, arg, L∂, abstract_∂, grid) where {LX, LY, LZ}
    ▶ = interpolation_operator(L∂, L)
    return Derivative{L[1], L[2], L[3]}(∂, arg, ▶, abstract_∂, grid)
end

# Recompute location of derivative
@inline at(loc, d::Derivative) = d.abstract_∂(loc, d.arg)

"""Return `Center` if given `Face` or `Face` if given `Center`."""
flip(::Type{Face}) = Center
flip(::Type{Center}) = Face

const LocationType = Union{Type{Face}, Type{Center}, Type{Nothing}}

"""Return the ``x``-derivative function acting at (`X`, `Y`, `Any`)."""
∂x(X::LocationType, Y::LocationType, Z::LocationType) = eval(Symbol(:∂x, interpolation_code(flip(X)), interpolation_code(Y), interpolation_code(Z)))

"""Return the ``y``-derivative function acting at (`X`, `Y`, `Any`)."""
∂y(X::LocationType, Y::LocationType, Z::LocationType) = eval(Symbol(:∂y, interpolation_code(X), interpolation_code(flip(Y)), interpolation_code(Z)))

"""Return the ``z``-derivative function acting at (`Any`, `Any`, `Z`)."""
∂z(X::LocationType, Y::LocationType, Z::LocationType) = eval(Symbol(:∂z, interpolation_code(X), interpolation_code(Y), interpolation_code(flip(Z))))

const derivative_operators = Set([:∂x, :∂y, :∂z])
push!(operators, derivative_operators...)

"""
    ∂x(L::Tuple, arg::AbstractField)

Return an abstract representation of an ``x``-derivative acting on field `a` followed
by interpolation to `L`, where `L` is a 3-tuple of `Face`s and `Center`s.
"""
∂x(L::Tuple, arg::AF{LX, LY, LZ}) where {LX, LY, LZ} =
    _derivative(L, ∂x(LX, LY, LZ), arg, (flip(LX), LY, LZ), ∂x, arg.grid)

"""
    ∂y(L::Tuple, arg::AbstractField)

Return an abstract representation of a ``y``-derivative acting on field `a` followed
by interpolation to `L`, where `L` is a 3-tuple of `Face`s and `Center`s.
"""
∂y(L::Tuple, arg::AF{LX, LY, LZ}) where {LX, LY, LZ} =
    _derivative(L, ∂y(LX, LY, LZ), arg, (LX, flip(LY), LZ), ∂y, arg.grid)

"""
    ∂z(L::Tuple, arg::AbstractField)

Return an abstract representation of a ``z``-derivative acting on field `a` followed
by  interpolation to `L`, where `L` is a 3-tuple of `Face`s and `Center`s.
"""
∂z(L::Tuple, arg::AF{LX, LY, LZ}) where {LX, LY, LZ} =
    _derivative(L, ∂z(LX, LY, LZ), arg, (LX, LY, flip(LZ)), ∂z, arg.grid)

# Defaults
"""
    ∂x(arg::AbstractField)

Return an abstract representation of a ``x``-derivative acting on field `a`.
"""
∂x(arg::AF{LX, LY, LZ}) where {LX, LY, LZ} = ∂x((flip(LX), LY, LZ), arg)

"""
    ∂y(arg::AbstractField)

Return an abstract representation of a ``y``-derivative acting on field `a`.
"""
∂y(arg::AF{LX, LY, LZ}) where {LX, LY, LZ} = ∂y((LX, flip(LY), LZ), arg)
"""
    ∂z(arg::AbstractField)

Return an abstract representation of a ``z``-derivative acting on field `a`.
"""
∂z(arg::AF{LX, LY, LZ}) where {LX, LY, LZ} = ∂z((LX, LY, flip(LZ)), arg)

#####
##### Nested computations
#####

compute_at!(∂::Derivative, time) = compute_at!(∂.arg, time)

#####

#####
##### GPU capabilities
#####

"Adapt `Derivative` to work on the GPU via CUDAnative and CUDAdrv."
Adapt.adapt_structure(to, deriv::Derivative{LX, LY, LZ}) where {LX, LY, LZ} =
    Derivative{LX, LY, LZ}(Adapt.adapt(to, deriv.∂),
                           Adapt.adapt(to, deriv.arg),
                           Adapt.adapt(to, deriv.▶),
                           nothing,
                           Adapt.adapt(to, deriv.grid))


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

mutable struct VirtualMachineScaleSetUpdateNetworkProfile <: SwaggerModel
    healthProbe::Any # spec type: Union{ Nothing, ApiEntityReference } # spec name: healthProbe
    networkInterfaceConfigurations::Any # spec type: Union{ Nothing, Vector{VirtualMachineScaleSetUpdateNetworkConfiguration} } # spec name: networkInterfaceConfigurations

    function VirtualMachineScaleSetUpdateNetworkProfile(;healthProbe=nothing, networkInterfaceConfigurations=nothing)
        o = new()
        validate_property(VirtualMachineScaleSetUpdateNetworkProfile, Symbol("healthProbe"), healthProbe)
        setfield!(o, Symbol("healthProbe"), healthProbe)
        validate_property(VirtualMachineScaleSetUpdateNetworkProfile, Symbol("networkInterfaceConfigurations"), networkInterfaceConfigurations)
        setfield!(o, Symbol("networkInterfaceConfigurations"), networkInterfaceConfigurations)
        o
    end
end # type VirtualMachineScaleSetUpdateNetworkProfile

const _property_map_VirtualMachineScaleSetUpdateNetworkProfile = Dict{Symbol,Symbol}(Symbol("healthProbe")=>Symbol("healthProbe"), Symbol("networkInterfaceConfigurations")=>Symbol("networkInterfaceConfigurations"))
const _property_types_VirtualMachineScaleSetUpdateNetworkProfile = Dict{Symbol,String}(Symbol("healthProbe")=>"ApiEntityReference", Symbol("networkInterfaceConfigurations")=>"Vector{VirtualMachineScaleSetUpdateNetworkConfiguration}")
Base.propertynames(::Type{ VirtualMachineScaleSetUpdateNetworkProfile }) = collect(keys(_property_map_VirtualMachineScaleSetUpdateNetworkProfile))
Swagger.property_type(::Type{ VirtualMachineScaleSetUpdateNetworkProfile }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_VirtualMachineScaleSetUpdateNetworkProfile[name]))}
Swagger.field_name(::Type{ VirtualMachineScaleSetUpdateNetworkProfile }, property_name::Symbol) =  _property_map_VirtualMachineScaleSetUpdateNetworkProfile[property_name]

function check_required(o::VirtualMachineScaleSetUpdateNetworkProfile)
    true
end

function validate_property(::Type{ VirtualMachineScaleSetUpdateNetworkProfile }, name::Symbol, val)
end


text:
Base.summary(ds::DS) =
"$(dimension(ds))-dimensional "*systemtype(ds)*" dynamical system"

# Credit to Sebastian Pfitzner
function printlimited(io, x; Δx = 0, Δy = 0)
    sz = displaysize(io)
    io2 = IOBuffer(); ctx = IOContext(io2, :limit => true, :compact => true,
    :displaysize => (sz[1]-Δy, sz[2]-Δx))
    if x isa AbstractArray
        Base.print_array(ctx, x)
        s = String(take!(io2))
        s = replace(s[2:end], "  " => ", ")
        Base.print(io, "["*s*"]")
    else
        Base.print(ctx, x)
        s = String(take!(io2))
        Base.print(io, s)
    end
end

printlimited(io, x::Number; kwargs...) = print(io, x)

function Base.show(io::IO, ds::DS)
    ps = 14
    text = summary(ds)
    u0 = get_state(ds)'
    println(io, text)
    prefix = rpad(" state: ", ps)
    print(io, prefix); printlimited(io, u0, Δx = length(prefix)); print(io, "\n")
    println(io,  rpad(" rule f: ", ps),     get_rule_for_print(ds))
    println(io,  rpad(" in-place? ", ps),   isinplace(ds))
    println(io,  rpad(" jacobian: ", ps),   jacobianstring(ds))
    print(io,    rpad(" parameters: ", ps))
    printlimited(io, printable(ds.p), Δx = length(prefix), Δy = 10)
end

printable(p::AbstractVector) = p'
printable(p::Nothing) = "nothing"
printable(p) = p

get_rule_for_print(a::SciMLBase.AbstractODEIntegrator) = eomstring(a.f.f)
get_rule_for_print(a::MinimalDiscreteIntegrator) = eomstring(a.f)
get_rule_for_print(a::DynamicalSystem) = eomstring(a.f)
get_rule_for_print(a) = get_rule_for_print(a.integ)

eomstring(f::Function) = nameof(f)
eomstring(f) = nameof(typeof(f))

jacobianstring(ds::DS) = isautodiff(ds) ? "ForwardDiff" : "$(eomstring(ds.jacobian))"


text:
function cards_gained_counter!( output::SimOutput, cards_gained::Vector{Int}, deckstatus; rep, deckindex, column)
    for card in cards_gained
        for elem in deckstatus
            if card == elem.card
                @inbounds output.card_sources[rep,deckindex,elem.rarity,column] += 1
            end
        end
    end
end

function sum_over_prints(collection, prints)
    sum = 0
    for p in prints
        sum += collection[p.index]
    end
    sum
end

function deckinfo(cardname, amount::Int; card_db = card_db)::NamedTuple{(:name, :amount, :prints),Tuple{String,Int64,Array{NamedTuple{(:index, :set, :rarity),Tuple{Int64,Symbol,Int64}},1}}}
    prints = findall(y -> y["name"] == cardname, card_db)
    if length(prints) == 0
        error("Unknown card $cardname")
    end
    (name = cardname, amount = amount,
     prints = map(i -> (index = i, set = card_db[i]["set"], rarity = card_db[i]["rarity"]), prints))
end

function reduce_deck(deck; additive = true, card_db = card_db)
    reduced = similar(deck, 0)

    for elem in deck
        ix = findfirst(x -> x.name == elem.name, reduced)

        if ix == nothing
            push!(reduced, elem)
        else
            if additive
                reduced[ix] = deckinfo(elem.name, min(4, reduced[ix].amount + elem.amount); card_db = card_db)
            else
                reduced[ix] = deckinfo(elem.name, min(4, max(reduced[ix].amount, elem.amount)); card_db = card_db)
            end
        end
    end

    reduced
end

"""
    deckinfo(deck::Vector{Tuple{String,Int}})

Processes a vector of card names and required quantities into a form that incorporates
set information, card rarity, and prints across multiple sets.
"""
function deckinfo(deck::Vector{Tuple{String,Int}}; card_db = card_db)
    reduce_deck(map(x -> deckinfo(x[1], x[2]; card_db = card_db), deck);
     additive = true, card_db = card_db)
end

function deckinfo(x::Deckinfo; card_db = card_db)
    reduce_deck(x; additive = true, card_db = card_db)
end

function icr_count(x)
    min = floor(Int, x)
    chc = x - min
    if rand() < chc
        return min + 1
    else
        return min
    end
end

max_stars_repo_name: asieev/ArenaSim

max_issues_repo_name: asieev/ArenaSim

max_forks_repo_name: asieev/ArenaSim


text:
using JuMP

is_approx_integer(x::Float64) = abs(x - round(x)) < 1e-8

function realize(tbl::Table, drawctx::ParentDrawContext)
    model = Model()

    m, n = size(tbl.children)

    abswidth = drawctx.box.a[1].value
    absheight = drawctx.box.a[2].value

    c_indexes = Tuple{Int, Int, Int}[]
    idx_cs = Dict{(Tuple{Int, Int}), Vector{Int}}()
    for i in 1:m, j in 1:n
        if length(tbl.children[i, j]) > 1
            for k in 1:length(tbl.children[i, j])
                push!(c_indexes, (i, j, k))

                if haskey(idx_cs, (i, j))
                    push!(idx_cs[(i,j)], length(c_indexes))
                else
                    idx_cs[(i,j)] = [length(c_indexes)]
                end
            end
        end
    end

    penalties = Array{Float64}(undef, length(c_indexes))
    for (l, (i, j, k)) in enumerate(c_indexes)
        penalties[l] = tbl.children[i, j][k].penalty
    end

    # 0-1 configuration variables for every cell with multiple configurations
    @defVar(model, c[1:length(c_indexes)], Bin)

    # width for every column
    @defVar(model, 0 <= w[1:n] <= abswidth)

    # height for every row
    @defVar(model, 0 <= h[1:m] <= absheight)

    # maximize the "size" of the focused cells
    @setObjective(model, Max, sum{w[j], j=tbl.x_focus} +
                              sum{h[i], i=tbl.y_focus} -
                              sum{penalties[i] * c[i], i=1:length(c_indexes)})

    # optional proportionality constraints
    if tbl.x_prop != nothing
        k1 = 1
        while k1 < length(tbl.x_focus) && isnan(tbl.x_prop[k1])
            k1 += 1
        end

        for k in 2:length(tbl.x_focus)
            isnan(tbl.x_prop[k]) && continue

            j1 = tbl.x_focus[k1]
            jk = tbl.x_focus[k]
            @addConstraint(model, w[j1] / tbl.x_prop[k1] ==  w[jk] / tbl.x_prop[k])
        end
    end

    if tbl.y_prop != nothing
        k1 = 1
        while k1 < length(tbl.y_focus) && isnan(tbl.y_prop[k1])
            k1 += 1
        end

        for k in 2:length(tbl.y_focus)
            isnan(tbl.y_prop[k]) && continue

            i1 = tbl.y_focus[k1]
            ik = tbl.y_focus[k]
            @addConstraint(model, h[i1] / tbl.y_prop[k1] ==  h[ik] / tbl.y_prop[k])
        end
    end

    # fixed configuration constraints: constrain a set of cells
    # to have tho same configuration.
    for fixed_config in tbl.fixed_configs
        isempty(fixed_config) && continue

        (i0, j0) = fixed_config[1]
        config_count = length(tbl.children[i0, j0])
        for (i, j) in fixed_config[2:end], k in 1:config_count
            !haskey(idx_cs, (i0, j0)) && !haskey(idx_cs, (i, j)) && continue
            idx_a = idx_cs[i0, j0][k]
            idx_b = idx_cs[(i,j)][k]
            @addConstraint(model, c[idx_a] == c[idx_b])
        end
    end

    # configurations are mutually exclusive
    for cgroup in groupby(l -> (c_indexes[l][1], c_indexes[l][2]),
                          1:length(c_indexes))
        @addConstraint(model, sum{c[l], l=cgroup} == 1)
    end

    # minimum cell size constraints for cells with multiple configurations
    for (l, (i, j, k)) in enumerate(c_indexes)
        minw = minwidth(tbl.children[i, j][k])
        minh = minheight(tbl.children[i, j][k])
        minw == nothing || @addConstraint(model, w[j] >= minw * c[l])
        minh == nothing || @addConstraint(model, h[i] >= minh * c[l])
    end

    # minimum cell size constraint for fixed cells
    for i in 1:m, j in 1:n
        if length(tbl.children[i, j]) == 1
            minw = minwidth(tbl.children[i, j][1])
            minh = minheight(tbl.children[i, j][1])
            minw == nothing || @addConstraint(model, w[j] >= minw)
            minh == nothing || @addConstraint(model, h[i] >= minh)
        end
    end

    # widths and heights must add up
    @addConstraint(model, sum{w[i], i=1:n} == abswidth)
    @addConstraint(model, sum{h[i], i=1:m} == absheight)

    status = solve(model,suppress_warnings=true)

    w_solution = getValue(w)[:]
    h_solution = getValue(h)[:]
    c_solution = getValue(c)

    if status == :Infeasible ||
            !all([is_approx_integer(c_solution[l]) for l in 1:length(c_indexes)])
        #println(STDERR, "JuMP: Infeasible")
        # The brute force solver is better able to select between various
        # non-feasible solutions. So we let it have a go.
        return realize_brute_force(tbl, drawctx)
    end

    # Set positions and sizes of children
    root = context(units=tbl.units, order=tbl.order)

    x_solution = cumsum([w_solution[j] for j in 1:n]) .- w_solution
    y_solution = cumsum([h_solution[i] for i in 1:m]) .- h_solution

    tbl.aspect_ratio == nothing ||
            force_aspect_ratio!(tbl, x_solution, y_solution, w_solution, h_solution)

    # set child positions according to layout solution
    feasible_eps = 1e-4
    feasible = true
    for i in 1:m, j in 1:n
        if length(tbl.children[i, j]) == 1
            ctx = copy(tbl.children[i, j][1])
            feasible == feasible && issatisfied(ctx, w_solution[j], h_solution[i])
            ctx.box = BoundingBox(
                x_solution[j]*mm, y_solution[i]*mm,
                w_solution[j]*mm, h_solution[i]*mm)
            compose!(root, ctx)
        end
    end

    for (l, (i, j, k)) in enumerate(c_indexes)
        if round(c_solution[l]) == 1
            ctx = copy(tbl.children[i, j][k])
            feasible == feasible && issatisfied(ctx, w_solution[j], h_solution[i])
            ctx.box = BoundingBox(
                x_solution[j]*mm, y_solution[i]*mm,
                w_solution[j]*mm, h_solution[i]*mm)
            compose!(root, ctx)
        end
    end

    feasible || warn("Graphic may not be drawn correctly at the given size.")

    return root
end