def driving_process(params, step, sL, s):

    #placeholder plumbing for random processes
    arrival_rate = 10 / (1 + s['sentiment'])
    rv1 = np.random.rand()
    new_participant = bool(rv1 < 1 / arrival_rate)
    supporters = get_edges_by_type(s['network'], 'support')

    len_parts = len(get_nodes_by_type(s['network'], 'participant'))
    supply = s['supply']
    expected_holdings = .1 * supply / len_parts
    if new_participant:
        h_rv = expon.rvs(loc=0.0, scale=expected_holdings)
        new_participant_holdings = h_rv
    else:
        new_participant_holdings = 0

    network = s['network']
    affinities = [network.edges[e]['affinity'] for e in supporters]
    median_affinity = np.median(affinities)

    proposals = get_nodes_by_type(network, 'proposal')
    fund_requests = [
        network.nodes[j]['funds_requested'] for j in proposals
        if network.nodes[j]['status'] == 'candidate'
    ]

    funds = s['funds']
    total_funds_requested = np.sum(fund_requests)

    proposal_rate = 1 / median_affinity * (1 + total_funds_requested / funds)
    rv2 = np.random.rand()
    new_proposal = bool(rv2 < 1 / proposal_rate)

    sentiment = s['sentiment']
    funds = s['funds']
    scale_factor = funds * sentiment**2 / 10000

    if scale_factor < 1:
        scale_factor = 1

    #this shouldn't happen but expon is throwing domain errors
    if sentiment > .4:
        funds_arrival = expon.rvs(loc=0, scale=scale_factor)
    else:
        funds_arrival = 0

    return ({
        'new_participant': new_participant,
        'new_participant_holdings': new_participant_holdings,
        'new_proposal': new_proposal,
        'funds_arrival': funds_arrival
    })
def complete_proposal(params, step, sL, s, _input):

    network = s['network']
    participants = get_nodes_by_type(network, 'participant')
    proposals = get_nodes_by_type(network, 'proposal')
    competitors = get_edges_by_type(network, 'conflict')

    completed = _input['completed']
    for j in completed:
        network.nodes[j]['status'] = 'completed'

        for c in proposals:
            if (j, c) in competitors:
                conflict = network.edges[(j, c)]['conflict']
                for i in participants:
                    network.edges[(i, c)]['affinity'] = network.edges[
                        (i, c)]['affinity'] * (1 - conflict)

        for i in participants:
            force = network.edges[(i, j)]['affinity']
            sentiment = network.nodes[i]['sentiment']
            network.nodes[i]['sentiment'] = get_sentimental(sentiment,
                                                            force,
                                                            decay=0)

    failed = _input['failed']
    for j in failed:
        network.nodes[j]['status'] = 'failed'
        for i in participants:
            force = -network.edges[(i, j)]['affinity']
            sentiment = network.nodes[i]['sentiment']
            network.nodes[i]['sentiment'] = get_sentimental(sentiment,
                                                            force,
                                                            decay=0)

    key = 'network'
    value = network

    return (key, value)